home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Archive-tools / binhex-vm-cms-files.txt < prev    next >
Internet Message Format  |  1989-07-06  |  137KB

  1. Date:         Fri, 05 Jun 87 00:18:28 EDT
  2. From: Peter DiCamillo <CMSMAINT%BROWNVM.BITNET@forsythe.stanford.edu>
  3. Subject:      BINHEX Command for CMS
  4.  
  5. BINHEX is a command I've written for IBM VM/CMS systems to process
  6. BinHex (HQX) and MacBinary format files stored on CMS disks.  BINHEX
  7. will check for CRC and other errors in the files, display the header
  8. information (Mac filename, creator, type, flags etc.), and convert
  9. files between the two formats.  User documentation is contained in
  10. BINHEX HELPCMS; directions for creating BINHEX MODULE are in the
  11. main source file, BINHEX ASSEMBLE.
  12.  
  13. Peter DiCamillo, Brown University Computer Center
  14. BITNET: CMSMAINT@BROWNVM
  15. Internet: CMSMAINT%BROWNVM@WISCVM.WISC.EDU
  16.  
  17. ---------------------------------------------------------------------
  18. Contents:
  19. BINHEX   ASSEMBLE    2453 lines    Main program
  20. BINHEX   HELPCMS     224 lines     User documentation
  21. XMDMGEN  C           62 lines      Waterloo C pgm. to generate XMDMTAB
  22. XMDMTAB  ASSEMBLE    46 lines      Table for XMODEM CRC calculation
  23.  
  24. Note: After uploading the ASSEMBLE files, they must be converted to
  25.       fixed-length 80-byte records in order to be assembled. For
  26.       example: COPYFILE BINHEX ASSEMBLE A = = = (LRECL 80 RECFM F
  27.  
  28. ---------- start of BINHEX ASSEMBLE: 2453 lines follow --------------
  29. BINHEX   TITLE 'Program to Process BinHex and MacBinary Format Files'
  30. BINHEX   CSECT
  31.          SPACE
  32. ***********************************************************************
  33. *                                                                     *
  34. *  Name:                                                              *
  35. *       BINHEX                                                        *
  36. *                                                                     *
  37. *  Author:                                                            *
  38. *       Peter DiCamillo                                               *
  39. *       Brown University Computer Center                              *
  40. *       Box 1885                                                      *
  41. *       Providence, RI 02912                                          *
  42. *       (401) 863-2221                                                *
  43. *       BITNET: CMSMAINT@BROWNVM                                      *
  44. *       ARPANET: CMSMAINT%BROWNVM@WISCVM.WISC.EDU                     *
  45. *                                                                     *
  46. *  Function:                                                          *
  47. *       BINHEX  checks,  describes,   and  converts Macintosh  files  *
  48. *       stored in CMS.   It is able to work with both MacBinary for-  *
  49. *       mat (Macterminal, BinHex 5.0) and BinHex format (BinHex 4.0)  *
  50. *       files.                                                        *
  51. *                                                                     *
  52. *  Command format:                                                    *
  53. *       BINHEX ?|Check|Describe|COnvert fn <ft <fm>> <( options <)>>  *
  54. *       See the HELP file for detailed information.                   *
  55. *                                                                     *
  56. *  Normal Exits:                                                      *
  57. *       Returns to CMS with R15 = 0.  For the ?, Check, and Describe  *
  58. *       operands, repsonses are generated before returning.           *
  59. *                                                                     *
  60. *  Error Conditions:                                                  *
  61. *       Returns to CMS  with a non-zero return code  after typing an  *
  62. *       error message. Errors messgae and return codes are listed in  *
  63. *       the HELP file.                                                *
  64. *                                                                     *
  65. *  CMS System Calls:                                                  *
  66. *       CMS nucleus  routines called  via BALR:                       *
  67. *       ESTATE, ESTATEW, ADTLKP, RDBUF, WRBUF, FINIS                  *
  68. *       CMS routines called via SVC 202 or 203:                       *
  69. *       IDENTIFY, CONWAIT, TYPLIN, ATTN, EXECCOMM, DMSERR, LINEDIT    *
  70. *                                                                     *
  71. *  External References:                                               *
  72. *       For CRC calculation, BINHEX uses a table defined in XMDMTAB   *
  73. *       ASSEMBLE.                                                     *
  74. *                                                                     *
  75. *  Attributes:                                                        *
  76. *       BINHEX loads  in the user program  area.   In order  to call  *
  77. *       nucleus  routines   via  BALR  (for  speed),    it  disables  *
  78. *       interrupts and runs with the system storage key.              *
  79. *                                                                     *
  80. ***********************************************************************
  81.          EJECT
  82. ***********************************************************************
  83. *                                                                     *
  84. *  Module Generation:                                                 *
  85. *       To create a new BINHEX MODULE, use the commands:              *
  86. *           GLOBAL TXTLIB DMSSP CMSLIB                                *
  87. *           ASSEMBLE BINHEX                                           *
  88. *           ASSEMBLE XMDMTAB                                          *
  89. *           LOAD BINHEX                                               *
  90. *           GENMOD BINHEX                                             *
  91. *                                                                     *
  92. *  Update History:                                                    *
  93. *       June 1, 1987: Initial implementation, Peter DiCamillo         *
  94. *                                                                     *
  95. ***********************************************************************
  96.          EJECT
  97.          PRINT NOGEN
  98.          REGEQU
  99.          USING *,R15
  100.          STM   R0,R15,REGSAVE      Save all registers
  101.          LR    R11,R15             Use R11-R13 as base registers
  102.          LA    R12,2048(R11)
  103.          LA    R12,2048(R12)
  104.          LA    R13,2048(R12)
  105.          LA    R13,2048(R13)
  106.          DROP  R15
  107.          USING BINHEX,R11,R12,R13
  108.          USING NUCON,0             Address nucon
  109.          L     R10,AFVS            R10 = FVSECT base register
  110.          USING FVSECT,R10
  111.          DMSKEY NUCLEUS            We need system key and no
  112.          SSM   =X'00'                interruptions
  113.          SR    R15,R15
  114.          ST    R15,RTNCODE         Return code initialized to zero
  115.          ST    R15,CPS             Initailize rate to zero
  116.          MVI   FLAGS,0             All flags = 0
  117.          MVI   FLAGS2,0
  118.          MVI   OPRCODE,C' '        First operand unknown
  119.          MVC   IFM(2),=CL2'*'      Default input mode is "*"
  120.          MVC   OFM(2),=CL2'*'      Default output mode is "*"
  121.          L     R2,=A(TOASCSTD)     Set default EBCDIC to ASCII table
  122.          ST    R2,TOASCADR
  123.          L     R2,=A(FRASCSTD)     Set default ASCII to EBCDIC table
  124.          ST    R2,FRASCADR
  125.          BAL   R14,GETID           Get local node id
  126.          CLC   NODEID(8),BROWNID   If Brown, use local tables
  127.          BNE   XTABOK
  128.          L     R2,=A(TOASCBRN)
  129.          ST    R2,TOASCADR
  130.          L     R2,=A(FRASCBRN)
  131.          ST    R2,FRASCADR
  132. XTABOK   EQU   *
  133.          L     R2,=A(WRITBUFF)     R2 -> buffer
  134.          L     R3,=A(VALIDTAB)     R3 -> TRT table
  135.          MVI   0(R3),X'FF'         Initialize VALIDTAB for TRTs
  136.          MVC   1(255,R3),0(R3)
  137.          L     R4,=A(BINTOASC)     R4 -> ASCII character list
  138.          MVC   0(64,R2),0(R4)      Copy valid ASCII characters
  139.          L     R4,FRASCADR         R2 -> ASCII-to-EBCDIC table
  140.          TR    0(64,R2),0(R4)      Convert to valid EBCDIC characters
  141.          LA    R4,64               R4 = count for BCT
  142.          SR    R5,R5               R5 = 0 for IC
  143. VINITLP  EQU   *                   Loop to fill-in VALIDTAB
  144.          IC    R5,0(R2)                 Get new character in R5
  145.          LA    R6,0(R3,R5)              R6 -> position in table
  146.          MVI   0(R6),0                  Store zero there
  147.          LA    R2,1(R2)                 R2 -> next character
  148.          BCT   R4,VINITLP               Repeat for all 64 character
  149.          B     OPERCHK             Skip over save area
  150.          SPACE
  151. REGSAVE  DS    8D                  Register save area
  152. RTNCODE  EQU   REGSAVE+60          Return code at location for R15
  153.          EJECT
  154. * Check for valid first operand (function)
  155. OPERCHK  LA    R1,8(R1)            R1 -> operand
  156.          CLI   0(R1),X'FF'         Operand there at all?
  157.          BE    BADFMT              No, give error message
  158.          LA    R3,8                Get operand length in R3
  159.          LA    R2,7(R1)            R2 -> last byte
  160. OPRLENLP EQU   *                   Loop to get length
  161.          CLI   0(R2),C' '               At non-blank?
  162.          BNE   HAVEOPRL                 Yes, length in R3
  163.          BCTR  R2,0                     R2 -> previous byte
  164.          BCT   R3,OPRLENLP              Decrement and repeat
  165.          B     BADFMT              All blank is error
  166.          SPACE
  167. HAVEOPRL BCTR  R3,0                Decrement length for EX
  168.          LA    R2,OPRTAB           R2 -> operand table
  169. OPRTBCHK EQU   *                   Look for match in table
  170.          CLI   0(R2),X'FF'              At table end?
  171.          BE    BADFMT                   Yes, format error
  172.          EX    R3,OPRCLC                Found a match?
  173.          BE    USEOPR                   Yes, handle operand
  174.          LA    R2,12(R2)                R2 -> next operand
  175.          B     OPRTBCHK                 Try again
  176.          SPACE
  177. OPRCLC   CLC   0(*-*,R2),0(R1)     Compare table entry to operand
  178.          SPACE
  179. USEOPR   L     R2,8(R2)            R2 -> operand code
  180.          BR    R2                  Execute code for operand
  181.          SPACE
  182. CHKOPR   MVI   OPRCODE,C'C'        Set code C for CHECK
  183.          B     READID
  184.          SPACE
  185. CVTOPR   MVI   OPRCODE,C'V'        Set code V for CONVERT
  186.          B     READID
  187.          SPACE
  188. DESCOPR  MVI   OPRCODE,C'D'        Set code D for DESCRIBE
  189.          B     READID
  190.          SPACE
  191. QUESOPR  EQU   *                   For ?, type command format
  192.          WRTERM 'Format is: BINHEX ?|Check|Describe|COnvert fn ft <fm> X
  193.                <( options <)>>'
  194.          WRTERM '  Options: <To fm> <Rate cps> <Stack> <Lifo> <Fifo> <SX
  195.                TEm stemname>'
  196.          B     CMSRTN              Return right away
  197.          SPACE
  198. * After function operand, get file id
  199. READID   LA    R1,8(R1)            R1 -> possible FN
  200.          CLI   0(R1),X'FF'         Error if missing or "*"
  201.          BE    BADFMT
  202.          CLI   0(R1),C'*'
  203.          BE    BADFMT
  204.          MVC   IFN(8),0(R1)        Copy FN
  205.          MVC   IFT(8),=CL8'*'      Set default filetype
  206.          LA    R1,8(R1)            R1 -> possible FT
  207.          CLI   0(R1),X'FF'         Done if no FT, FM or options
  208.          BE    OPTDONE
  209.          CLI   0(R1),C'('          If '(', start options
  210.          BE    OPTSCAN
  211.          MVC   IFT(8),0(R1)        Copy FT
  212.          LA    R1,8(R1)            R1 -> past FT
  213.          CLI   0(R1),X'FF'         Done if no FM or options
  214.          BE    OPTDONE
  215.          CLI   0(R1),C'('          If '(', start options
  216.          BE    OPTSCAN
  217.          CLI   2(R1),C' '          3rd character of FM must be blank
  218.          BNE   BADFMT
  219.          CLC   0(2,R1),=CL2'*'     Skip copy if default specified
  220.          BE    IFMDONE
  221.          MVC   IFM(2),0(R1)        Copy filemode for input
  222.          CLI   IFM+1,C' '          If no mode number, use '1'
  223.          BNE   IFMDONE
  224.          MVI   IFM+1,C'1'
  225. IFMDONE  LA    R1,8(R1)            R1 -> next argument
  226.          CLI   0(R1),X'FF'         Done if no options
  227.          BE    OPTDONE
  228.          CLI   0(R1),C'('          If '(', start options
  229.          BE    OPTSCAN
  230. *                                  Else command format error
  231. BADFMT   LR    R2,R1               R2 = scan pointer
  232.          S     R2,=F'8'            Point to previous token
  233.          DMSERR NUM=1,LET=E,SUB=(CHARA,(R2)),                          X
  234.                TEXT='Error in command after ''........'''
  235.          DMSERR NUM=2,LET=I,                                           X
  236.                TEXT='Issue BINHEX ? or HELP CMS BINHEX for more informaX
  237.                tion'
  238.          MVI   RTNCODE+3,24        Set return code
  239.          B     CMSRTN              Return to CMS
  240.          SPACE
  241. * Process options
  242. OPTSCAN  EQU   *                   R1 -> '('
  243. NEWOPT   LA    R1,8(R1)            R1 -> possible option
  244.          CLI   0(R1),X'FF'         Option there?
  245.          BE    OPTDONE             No, done scanning
  246.          CLI   0(R1),C')'          Also done if ')'
  247.          BE    OPTDONE
  248.          LA    R3,8                Get option length in R3
  249.          LA    R2,7(R1)            R2 -> last byte
  250. OPTLENLP EQU   *                   Loop to get length
  251.          CLI   0(R2),C' '               At non-blank?
  252.          BNE   HAVEOPTL                 Yes, length in R3
  253.          BCTR  R2,0                     R2 -> previous byte
  254.          BCT   R3,OPTLENLP              Decrement and repeat
  255.          B     BADOPT              All blank is error
  256.          SPACE
  257. HAVEOPTL BCTR  R3,0                Decrement length for EX
  258.          LA    R2,OPTTAB           R2 -> option table
  259. OPTTBCHK EQU   *                   Look for match in table
  260.          CLI   0(R2),X'FF'              At table end?
  261.          BE    BADOPT                   Yes, format error
  262.          EX    R3,OPTCLC                Found a match?
  263.          BE    USEOPT                   Yes, handle option
  264.          LA    R2,12(R2)                R2 -> next option
  265.          B     OPTTBCHK                 Try again
  266.          SPACE
  267. OPTCLC   CLC   0(*-*,R2),0(R1)     Compare table entry to option
  268.          SPACE
  269. USEOPT   L     R2,8(R2)            R2 -> option code
  270.          BR    R2                  Execute code for option
  271.          SPACE
  272. TOOPT    EQU   *                   TO option
  273.          LA    R1,8(R1)            R1 -> filemode
  274.          CLI   0(R1),X'FF'         Error if mode missing
  275.          BE    BADMODE
  276.          CLI   2(R1),C' '          Error if more than 2 characters
  277.          BNE   BADMODE
  278.          MVC   OFM(2),0(R1)        Copy output filemode
  279.          B     NEWOPT
  280.          SPACE
  281. STEMOPT  EQU   *                   STEM option
  282.          LA    R1,8(R1)            R1 -> stem name
  283.          CLI   0(R1),X'FF'         Error if stem missing
  284.          BE    BADSTEM
  285.          MVC   STEMNAME(8),0(R1)   Save stem name
  286.          OI    FLAGS2,EXECVAR      Remember stem given
  287.          LA    R3,8                Get stem length in R3
  288.          LA    R2,7(R1)            R2 -> last byte
  289. STMLENLP EQU   *                   Loop to get length
  290.          CLI   0(R2),C' '               At non-blank?
  291.          BNE   HAVESTML                 Yes, length in R3
  292.          BCTR  R2,0                     R2 -> previous byte
  293.          BCT   R3,STMLENLP              Decrement and repeat
  294.          B     BADSTEM             Error if all blank
  295.          SPACE
  296. HAVESTML ST    R3,STEMSIZE         Save length of stem name
  297.          B     NEWOPT
  298.          SPACE
  299. BADMODE  LR    R2,R1               R2 -> bad filemode
  300.          DMSERR NUM=48,LET=E,TEXT='Invalid mode ''........''',         X
  301.                SUB=(CHARA,(R2))
  302.          MVI   RTNCODE+3,24        Set return code
  303.          B     CMSRTN              Return to CMS
  304.          SPACE
  305. BADSTEM  DMSERR NUM=637,LET=E,TEXT='Missing value for the ''STEM'' optiX
  306.                on'
  307.          MVI   RTNCODE+3,24        Set return code
  308.          B     CMSRTN              Return to CMS
  309.          SPACE
  310. RATEOPT  EQU   *                   RATE option
  311.          LA    R1,8(R1)            R1 -> rate
  312.          CLI   0(R1),X'FF'         Error if rate missing
  313.          BE    BADRATE
  314.          BAL   R14,DECCVT          Convert to decimal in R2
  315.          BNP   BADRATE             Error if result not positive
  316.          ST    R2,CPS              Store rate
  317.          B     NEWOPT              Ready for next option
  318.          SPACE
  319. BADRATE  LR    R2,R1               R2 -> bad rate
  320.          DMSERR NUM=10,LET=E,TEXT='Invalid rate ''........''',         X
  321.                SUB=(CHARA,(R2))
  322.          MVI   RTNCODE+3,24        Set return code
  323.          B     CMSRTN              Return to CMS
  324.          SPACE
  325. STKOPT   EQU   *                   STACK or FIFO option
  326.          OI    FLAGS,STKDESC       Set flag to stack description
  327.          B     NEWOPT
  328.          SPACE
  329. LIFOOPT  EQU   *                   LIFO option
  330.          OI    FLAGS,STKDESC+STKLIFO  Set stack and FIFO flags
  331.          B     NEWOPT
  332.          SPACE
  333. BADOPT   LR    R2,R1               R2 -> bad option
  334.          DMSERR NUM=3,LET=E,TEXT='Invalid option ''........''',        X
  335.                SUB=(CHARA,(R2))
  336.          MVI   RTNCODE+3,24        Set return code
  337.          B     CMSRTN              Return to CMS
  338.          SPACE
  339. OPTDONE  EQU   *                   Done scanning plist
  340. * Check input file, get actual filemode, and check for BIN file
  341.          LA    R1,INPLIST          Call STATE for input file
  342.          L     R15,AESTATE
  343.          BALR  R14,R15
  344.          BNZ   STATERR             Check for any errors
  345.          CLC   IFT(8),=CL8'*'      * or no filetype specified?
  346.          BNE   FTOK                No, keep filetype
  347.          MVC   IFT(8),FVST         Else copy from file we found
  348. FTOK     CLC   FVSIL(4),=F'256'    Return error if lrecl too big
  349.          BH    LRECLERR
  350.          L     R2,FVSFSTAD         R2 -> ADT for input file disk
  351.          USING ADTSECT,R2
  352.          IC    R1,ADTM             Fill-in actual disk letter and
  353.          STC   R1,IFM                mode number for file which
  354.          IC    R1,FVSM+1             was found
  355.          STC   R1,IFM+1
  356.          DROP  R2
  357.          CLI   OFM,C'*'            If OFM not filled-in, use input
  358.          BNE   MDNUMTST              file disk letter
  359.          IC    R1,IFM
  360.          STC   R1,OFM
  361. MDNUMTST CLI   OFM+1,C' '          If OFM not filled-in, use input
  362.          BNE   BINCHK                file mode number
  363.          IC    R1,IFM+1
  364.          STC   R1,OFM+1
  365. BINCHK   EQU   *                   Check for MacBinary input file
  366.          CLI   FVSFV,C'F'          Is recfm F?
  367.          BNE   NOTBIN              No, not MacBinary
  368.          CLC   FVSIL(4),=F'128'    Is lrecl 128?
  369.          BNE   NOTBIN              No, not MacBinary
  370.          OI    FLAGS,MACBIN        Else set flag for MacBinary
  371. NOTBIN   EQU   *
  372. * Define input file RDBUF plist
  373.          LA    R0,1                R0 = 1 for initializing
  374.          SR    R15,R15             R15 = 0 for initializing
  375.          MVC   INCMMD(8),=CL8'RDBUF'  Command name
  376.          STH   R15,RDUN1           Unused halfword
  377.          L     R1,=A(READBUFF)     Buffer address
  378.          ST    R1,RDADDR
  379.          MVC   RDBUFLTH(4),=F'256'  Buffer size
  380.          MVI   RDFV,C'V'           Record format (works for F too)
  381.          MVI   RDFLAG,X'20'        Plist flag
  382.          STH   R15,RDUN2           Unused halfword
  383.          ST    R15,RDLGTH          Bytes read
  384.          ST    R15,RDITEM          Item number
  385.          ST    R0,RDITEC           Item count
  386.          ST    R15,RDWP            Write and read pointers
  387.          ST    R15,RDRP
  388. * If CONVERT specified, check output file status
  389.          CLI   OPRCODE,C'V'        Convert specified?
  390.          BNE   INITDONE            No, ready to start processing
  391.          MVC   OFN(8),IFN          Output filename same as input
  392.          MVC   OFT(8),=CL8'BIN'    Assume BIN for filetype
  393.          TM    FLAGS,MACBIN        Is input MACBIN?
  394.          BZ    KEEPOFT             No, BIN is correct
  395.          MVC   OFT(8),=CL8'HQX'    Else use HQX
  396. KEEPOFT  EQU   *                   OFM already defined
  397.          LA    R1,OUTPLIST         Call STATEW for output file
  398.          L     R15,AESTATEW
  399.          BALR  R14,R15
  400.          C     R15,=F'28'          Error if "File not found"
  401.          BNE   EXIERR                not returned
  402.          LA    R1,OUTPLIST         Get ADT for output disk
  403.          L     R15,VCADTLKP
  404.          BALR  R14,R15
  405.          BNZ   ROERR               (should not happen due to STATE)
  406.          LR    R2,R1               Check disk is R/W
  407.          USING ADTSECT,R2
  408.          TM    ADTFLG1,ADTFRW      Is disk R/W?
  409.          BZ    ROERR               No, give error
  410.          DROP  R2
  411. * Define output file WRBUF plist
  412.          LA    R0,1                R0 = 1 for initializing
  413.          SR    R15,R15             R15 = 0 for initializing
  414.          MVC   OUTCMMD(8),=CL8'WRBUF'  Command name
  415.          STH   R15,WRUN1           Unused halfword
  416.          L     R1,=A(WRITBUFF)     Buffer address
  417.          ST    R1,WRADDR
  418.          ST    R15,WRBUFLTH        Buffer size (will be set)
  419.          MVI   WRFV,C'V'           Record format
  420.          TM    FLAGS,MACBIN        MacBinary input file
  421.          BO    KEEPVAR             Yes, keep recfm V
  422.          MVC   WRBUFLTH(4),=F'128' Lrecl 128 and recfm F for
  423.          MVI   WRFV,C'F'             MacBinary output
  424. KEEPVAR  MVI   WRFLAG,X'20'        Plist flag
  425.          STH   R15,WRUN2           Unused halfword
  426.          ST    R15,WRUN3           Unused word
  427.          ST    R15,WRITEM          Item number
  428.          ST    R0,WRITEC           Item count
  429.          ST    R15,WRWP            Write and read pointers
  430.          ST    R15,WRRP
  431. INITDONE EQU   *                   Ready to process files
  432.          XC    HDREC(128),HDREC    Initialize header info.
  433.          XC    CHRTOTAL(4),CHRTOTAL  Initialize count of characters
  434.          TM    FLAGS,MACBIN        Separate processing for MacBinary
  435.          BO    BINPROC               file format
  436. *
  437. * Read BinHex file to define file header info
  438. *
  439.          LA    R1,CVCNT0           Reset left over bit
  440.          ST    R1,BINXTADR           processing
  441.          MVI   CMPCNT,0            Reset compression count
  442.          XC    BINLEN(4),BINLEN    Reset count for BINBUFF
  443.          XC    CRCVAL(2),CRCVAL    Reset CRC
  444.          LA    R0,1                R0 = length
  445.          LA    R1,HDFNLEN          R1 -> buffer
  446.          BAL   R14,GETSTR          Get length of filename
  447.          BAL   R14,CRCCALC         Include in CRC
  448.          SR    R1,R1               Get length in R1
  449.          IC    R1,HDFNLEN
  450.          LTR   R1,R1               Skip getting name if zero
  451.          BZ    NONAME
  452.          C     R1,=F'63'           If >63, use 63
  453.          BNH   FNLENOK
  454.          L     R1,=F'63'
  455. FNLENOK  LR    R0,R1               R0 = length
  456.          LA    R1,HDFN             R1 -> buffer
  457.          BAL   R14,GETSTR          Get filename
  458.          BAL   R14,CRCCALC         Include in CRC
  459. NONAME   LA    R0,1                R0 = length
  460.          LA    R1,HDVER            R1 -> buffer
  461.          BAL   R14,GETSTR          Get version byte
  462.          BAL   R14,CRCCALC         Include in CRC
  463.          LA    R0,10               R0 = length
  464.          LA    R1,HDFTYP           R1 -> buffer
  465.          BAL   R14,GETSTR          Get type, creator, flag bytes
  466.          BAL   R14,CRCCALC         Include in CRC
  467.          LA    R0,8                R0 = length
  468.          LA    R1,HDDATALN         R1 -> buffer
  469.          BAL   R14,GETSTR          Get lengths of forks
  470.          BAL   R14,CRCCALC         Include in CRC
  471.          LA    R0,2                R0 = length
  472.          L     R1,=A(DATABUFF)     R1 -> buffer
  473.          BAL   R14,GETSTR          Get header CRC
  474.          BAL   R14,CRCCALC         Include in CRC
  475.          CLC   CRCVAL(2),=H'0'     Is final CRC 0?
  476.          BE    HDCHKOK             Yes, continue
  477.          DMSERR LET=E,NUM=7,TEXT='''....................'': CRC error fX
  478.                or BinHex header',SUB=(CHAR8A,IFN)
  479.          MVI   RTNCODE+3,44        Set RC = 44
  480.          B     CMSRTN              Return to caller
  481.          SPACE
  482. HDCHKOK  EQU   *                   HQX header successfully read
  483.          CLI   OPRCODE,C'V'        Conversion wanted?
  484.          BNE   HDDESC              No, check for description
  485.          LA    R1,HDREC            Output header record
  486.          BAL   R14,WR128
  487.          B     CHKDATA             Ready for data fork
  488.          SPACE
  489. HDDESC   CLI   OPRCODE,C'D'        Description wanted?
  490.          BNE   CHKDATA             No, ready for data fork
  491.          TM    FLAGS2,EXECVAR      Header info. wanted in vars.?
  492.          BO    HDVAR1
  493.          BAL   R14,TYPEHDR         Type header description
  494.          B     CHKDATA             Ready for data fork
  495.          SPACE
  496. HDVAR1   BAL   R14,VARHDR          Return info. in vars.
  497. CHKDATA  EQU   *                   Check data fork
  498.          ICM   R3,B'1111',HDDATALN Get data fork length
  499.          LR    R4,R3               R4 = number of 128-byte pieces
  500.          SRL   R4,7
  501.          LR    R5,R4               R5 = bytes for all pieces
  502.          SLL   R5,7
  503.          SR    R3,R5               R3 = bytes left over
  504.          LA    R0,128              R0 = byte count
  505.          L     R1,=A(DATABUFF)     R1 -> buffer
  506.          XC    CRCVAL(2),CRCVAL    Reset CRC
  507.          LTR   R4,R4               Any pieces to read?
  508.          BNP   DCHKLEFT            No, skip loop
  509. DCHKLP   EQU   *                   Loop to read 128-byte pieces
  510.          BAL   R14,GETSTR               Read 128 bytes
  511.          BAL   R14,CRCCALC              Include in CRC
  512.          CLI   OPRCODE,C'V'             Conversion wanted?
  513.          BNE   DCHKNXT                  No, continue
  514.          BAL   R14,WR128                Write data block
  515. DCHKNXT  BCT   R4,DCHKLP                Repeat for all pieces
  516. DCHKLEFT LTR   R3,R3               Any bytes left?
  517.          BNP   DCHKEND             No, compare CRC
  518.          XC    0(128,R1),0(R1)     Initialize buffer
  519.          LR    R0,R3               Length = bytes left
  520.          BAL   R14,GETSTR          Read bytes
  521.          BAL   R14,CRCCALC         Include in CRC
  522.          CLI   OPRCODE,C'V'        Conversion wanted?
  523.          BNE   DCHKEND             No, continue
  524.          BAL   R14,WR128           Write data block
  525. DCHKEND  LA    R0,2                Get CRC
  526.          BAL   R14,GETSTR
  527.          BAL   R14,CRCCALC         Include CRC
  528.          CLC   CRCVAL(2),=H'0'     Is result zero?
  529.          BE    CHKRSC              Yes, check resource fork
  530.          DMSERR LET=E,NUM=8,TEXT='''....................'': CRC error fX
  531.                or BinHex data fork',SUB=(CHAR8A,IFN)
  532.          MVI   RTNCODE+3,44        Set RC = 44
  533.          B     CMSRTN              Return to caller
  534.          SPACE
  535. CHKRSC   EQU   *                   Check resource fork
  536.          ICM   R3,B'1111',HDRSCLN  Get resource fork length
  537.          LR    R4,R3               R4 = number of 128-byte pieces
  538.          SRL   R4,7
  539.          LR    R5,R4               R5 = bytes for all pieces
  540.          SLL   R5,7
  541.          SR    R3,R5               R3 = bytes left over
  542.          LA    R0,128              R0 = byte count
  543.          L     R1,=A(DATABUFF)     R1 -> buffer
  544.          XC    CRCVAL(2),CRCVAL    Reset CRC
  545.          LTR   R4,R4               Any pieces to read?
  546.          BNP   RCHKLEFT            No, skip loop
  547. RCHKLP   EQU   *                   Loop to read 128-byte pieces
  548.          BAL   R14,GETSTR               Read 128 bytes
  549.          BAL   R14,CRCCALC              Include in CRC
  550.          CLI   OPRCODE,C'V'             Conversion wanted?
  551.          BNE   RCHKNXT                  No, continue
  552.          BAL   R14,WR128                Write data block
  553. RCHKNXT  BCT   R4,RCHKLP                Repeat for all pieces
  554. RCHKLEFT LTR   R3,R3               Any bytes left?
  555.          BNP   RCHKEND             No, compare CRC
  556.          XC    0(128,R1),0(R1)     Initialize buffer
  557.          LR    R0,R3               Length = bytes left
  558.          BAL   R14,GETSTR          Read bytes
  559.          BAL   R14,CRCCALC         Include in CRC
  560.          CLI   OPRCODE,C'V'        Conversion wanted?
  561.          BNE   RCHKEND             No, continue
  562.          BAL   R14,WR128           Write data block
  563. RCHKEND  LA    R0,2                Get CRC
  564.          BAL   R14,GETSTR
  565.          BAL   R14,CRCCALC         Include CRC
  566.          CLC   CRCVAL(2),=H'0'     Is result 0?
  567.          BNE   RCHKERR             No, give error
  568. RSCDONE  EQU   *                   BinHex code continues here
  569.          CLI   OPRCODE,C'D'        Describe specified?
  570.          BE    DESCEND             Yes, finish description
  571.          CLI   OPRCODE,C'C'        Check specified?
  572.          BNE   CMSRTN              No, ready to return
  573.          CLI   REGSAVE+4,X'0B'     Called from command line?
  574.          BNE   CMSRTN              No, ready to return
  575.          L     R8,=A(DATABUFF)     R8 -> work buffer
  576.          LINEDIT TEXT='''....................'': No errors detected',  X
  577.                SUB=(CHAR8A,IFN),BUFFA=(R8),DISP=NONE,RENT=NO
  578.          BAL   R14,TYPEDESC        Type or stack line
  579.          B     CMSRTN
  580.          SPACE
  581. DESCEND  EQU   *                   End file description
  582.          L     R8,=A(DATABUFF)     R8 -> work buffer
  583.          L     R0,CHRTOTAL         R0 = character count
  584.          TM    FLAGS2,EXECVAR      Data in EXEC variables?
  585.          BZ    ENDTEXT             No, do text
  586.          L     R1,=A(AVAR13)       R1 -> CHARCNT string data
  587.          LR    R2,R1               Save R1 across NUMTOSTR
  588.          LA    R1,1(R8)            R1 -> buffer for number
  589.          BAL   R14,NUMTOSTR        Convert to string
  590.          STC   R0,0(R8)            Store string length
  591.          LR    R1,R2               Restore R1 for SETVAR
  592.          BAL   R14,SETVAR          Define stem.RESCSIZE
  593.          L     R4,CPS              Was rate specified?
  594.          LTR   R4,R4               (Check if non-zero)
  595.          BZ    CMSRTN              No, ready to return
  596.          SR    R5,R5               R5 = message length
  597.          LA    R6,1(R8)            R6 -> next byte
  598.          B     TIMEMSG             Join code for time estimate
  599.          SPACE
  600. ENDTEXT  MVC   1(17,R8),=C'Character count: '  Copy start of message
  601.          LA    R5,17               R5 = message length
  602.          LA    R6,1(R5,R8)         R6 -> next byte
  603.          LR    R1,R6               R1 -> buffer
  604.          BAL   R14,NUMTOSTR        Store number in string form
  605.          AR    R5,R0               Update length and address
  606.          AR    R6,R0
  607.          MVI   0(R6),C'.'          Append period
  608.          LA    R5,1(R5)            Update length and address
  609.          LA    R6,1(R6)
  610.          STC   R5,0(R8)            Store length for TYPEDESC
  611.          L     R4,CPS              Was rate specified?
  612.          LTR   R4,R4               (Check if non-zero)
  613.          BZ    RATEMSG             No, ready to type message
  614.          BCTR  R6,0                R6 -> ending period
  615.          MVC   0(2,R6),=C' ('      Replace by blank, paren
  616.          LA    R5,1(R5)            Adjust length for blank, paren
  617.          LA    R6,2(R6)            R6 -> next byte
  618. TIMEMSG  SR    R2,R2               R2, R3 = character count
  619.          L     R3,CHRTOTAL
  620.          DR    R2,R4               Divide to get seconds in R3
  621.          SRL   R4,1                R4 = half of divisor
  622.          CR    R2,R4               Remainder more than half?
  623.          BNH   KEEPSEC             No, keep seconds
  624.          A     R3,=F'1'            Else add one second
  625. KEEPSEC  SR    R2,R2               R2, R3 = seconds
  626.          D     R2,=F'60'           R2 = secs., R3 = mins.
  627.          LR    R4,R2               Save seconds in R4
  628.          SR    R2,R2               R2, R3 = minutes
  629.          D     R2,=F'60'           R2 = minutes, R3 = hours
  630.          LTR   R0,R3               Any hours?
  631.          BZ    INCMIN              No, ready for minutes
  632.          LR    R1,R6               R1 -> buffer
  633.          BAL   R14,NUMTOSTR        Store string there
  634.          AR    R5,R0               Adjust length and address
  635.          AR    R6,R0
  636.          C     R3,=F'1'            Just one hour?
  637.          BE    ONEHOUR             Yes, special case
  638.          MVC   0(8,R6),=C' hours, '  Append text
  639.          LA    R5,8(R5)            Adjust length and address
  640.          LA    R6,8(R6)
  641.          B     INCMIN              Ready for minutes
  642.          SPACE
  643. ONEHOUR  MVC   0(7,R6),=C' hour, '  Append text
  644.          LA    R5,7(R5)            Adjust length and address
  645.          LA    R6,7(R6)
  646. INCMIN   LTR   R0,R2               Any minutes?
  647.          BZ    INCSEC              No, ready for seconds
  648.          LR    R1,R6               R1 -> buffer
  649.          BAL   R14,NUMTOSTR        Store string there
  650.          AR    R5,R0               Adjust length and address
  651.          AR    R6,R0
  652.          C     R2,=F'1'            Just one minute?
  653.          BE    ONEMIN              Yes, special case
  654.          MVC   0(10,R6),=C' minutes, '  Append text
  655.          LA    R5,10(R5)           Adjust length and address
  656.          LA    R6,10(R6)
  657.          B     INCSEC              Ready for minutes
  658.          SPACE
  659. ONEMIN   MVC   0(9,R6),=C' minute, '  Append text
  660.          LA    R5,9(R5)            Adjust length and address
  661.          LA    R6,9(R6)
  662. INCSEC   LR    R0,R4               R0 = number to convert
  663.          LR    R1,R6               R1 -> buffer
  664.          BAL   R14,NUMTOSTR        Store string there
  665.          AR    R5,R0               Adjust length and address
  666.          AR    R6,R0
  667.          C     R4,=F'1'            Just one second?
  668.          BE    ONESEC              Yes, special case
  669.          MVC   0(12,R6),=C' seconds at '  Append text
  670.          LA    R5,12(R5)           Adjust length and address
  671.          LA    R6,12(R6)
  672.          B     ENDTIME             Ready to use text
  673.          SPACE
  674. ONESEC   MVC   0(11,R6),=C' second at '  Append text
  675.          LA    R5,11(R5)           Adjust length and address
  676.          LA    R6,11(R6)
  677. ENDTIME  L     R0,CPS              R0 = number to convert
  678.          LR    R1,R6               R1 -> buffer
  679.          BAL   R14,NUMTOSTR        Store string there
  680.          AR    R5,R0               Adjust length and address
  681.          AR    R6,R0
  682.          TM    FLAGS2,EXECVAR      Is this for EXEC data
  683.          BO    TIMEVAR             Yes, end differently
  684.          MVC   0(6,R6),=C' cps).'  Append text
  685.          LA    R5,6(R5)            Update length
  686.          STC   R5,0(R8)            Store new length for TYPEDESC
  687. RATEMSG  BAL   R14,TYPEDESC        Type or stack line
  688.          B     CMSRTN
  689.          SPACE
  690. TIMEVAR  MVC   0(4,R6),=C' cps'    Append text
  691.          LA    R5,4(R5)            Update length
  692.          STC   R5,0(R8)            Store new length for TYPEDESC
  693.          L     R1,=A(AVAR14)       R1 -> TIMEEST string data
  694.          BAL   R14,SETVAR          Define stem.TIMEEST
  695.          B     CMSRTN              Ready to return
  696.          SPACE
  697. RCHKERR  DMSERR LET=E,NUM=9,TEXT='''....................'': CRC error fX
  698.                or BinHex resource fork',SUB=(CHAR8A,IFN)
  699.          MVI   RTNCODE+3,44        Set RC = 44
  700.          B     CMSRTN              Return to caller
  701.          SPACE
  702. BINPROC  EQU   *                   Process MacBinary file
  703.          BAL   R14,GETLINE         Read 128-byte header record
  704.          LTR   R15,R15             Check for EOF (strange)
  705.          BNZ   GSEOF               Use error code in GETSTR
  706.          L     R2,=A(READBUFF)     R2 -> I/O buffer
  707.          MVC   HDREC(128),0(R2)    Copy data to header area
  708.          CLI   OPRCODE,C'V'        Conversion wanted?
  709.          BNE   BINHDESC            No, check for description
  710. *                                  Initialize for HQX output:
  711.          L     R1,=A(HQXMSG)       R1 -> initial message line
  712.          L     R2,=A(WRITBUFF)     R2 -> output buffer
  713.          MVC   0(HQXMSGL,R2),0(R1) Copy message to buffer
  714.          LA    R1,HQXMSGL          Get message length
  715.          ST    R1,WRLEN            Store as line length
  716.          BAL   R14,HQXLINE         Output line to file
  717.          MVI   0(R2),C' '          Output one blank
  718.          LA    R1,1                Length = 1
  719.          ST    R1,WRLEN
  720.          BAL   R14,HQXLINE         Write blank line
  721.          MVI   0(R2),C':'          Initialize buffer with colon
  722.          ST    R1,WRLEN
  723.          XC    EXPLEN(4),EXPLEN    Zero length for EXPBUFF
  724.          MVI   CMPMODE,0           Initial compression mode
  725. *                                  Output HQX header data:
  726.          XC    CRCVAL(2),CRCVAL    Reset CRC
  727.          SR    R2,R2               Get length of filename
  728.          IC    R2,HDFNLEN
  729.          LA    R0,1(R2)            R0 = length with length byte
  730.          LA    R1,HDFNLEN          R1 -> length
  731.          BAL   R14,HQXPUT          Output to HQX file
  732.          BAL   R14,CRCCALC         Include in CRC
  733.          LA    R0,1                R0 = 1 for version byte
  734.          LA    R1,HDVER            R1 -> version byte
  735.          BAL   R14,HQXPUT          Output version byte
  736.          BAL   R14,CRCCALC         Include in CRC
  737.          ICM   R2,B'0011',HDFLAGS  Save flag bits
  738.          NC    HDFLAGS(2),=X'F800' For HQX, 'and' with X'F800'
  739.          LA    R0,10               R0 = 10 (4+4+2)
  740.          LA    R1,HDFTYP           R1 -> type
  741.          BAL   R14,HQXPUT          Output type, creator, flags
  742.          BAL   R14,CRCCALC         Include in CRC
  743.          STCM  R2,B'0011',HDFLAGS  Restore original flag bits
  744.          LA    R0,8                R0 = 8 (4+4)
  745.          LA    R1,HDDATALN         R1 -> lengths
  746.          BAL   R14,HQXPUT          Output data and resource lengths
  747.          BAL   R14,CRCCALC         Include in CRC
  748.          LA    R0,2                Include X'0000' in CRC
  749.          LA    R1,=H'0'
  750.          BAL   R14,CRCCALC
  751.          LA    R0,2                R0 = length of CRC
  752.          LA    R1,CRCVAL           R1 -> CRC
  753.          BAL   R14,HQXPUT          End header with CRC
  754.          B     BINDATA             Ready for data fork
  755.          SPACE
  756. BINHDESC CLI   OPRCODE,C'D'        Description wanted?
  757.          BNE   BINDATA             No, ready for data fork
  758.          TM    FLAGS2,EXECVAR      Header info. wanted in vars.?
  759.          BO    HDVAR2
  760.          BAL   R14,TYPEHDR         Type header description
  761.          B     BINDATA             Ready for data fork
  762.          SPACE
  763. HDVAR2   BAL   R14,VARHDR          Return info. in vars.
  764. BINDATA  EQU   *                   Process BinHex data fork
  765.          ICM   R3,B'1111',HDDATALN Get data fork length
  766.          LR    R4,R3               R4 = number of 128-byte records
  767.          SRL   R4,7
  768.          LR    R5,R4               R5 = bytes for all records
  769.          SLL   R5,7
  770.          SR    R3,R5               R3 = bytes left over
  771.          LA    R0,128              R0 = byte count
  772.          L     R1,=A(READBUFF)     R1 -> buffer
  773.          XC    CRCVAL(2),CRCVAL    Reset CRC
  774.          LTR   R4,R4               Any entire records to read?
  775.          BNP   BINDLEFT            No, skip loop
  776. BINDLP   EQU   *                   Loop to read 128-byte records
  777.          BAL   R14,GETLINE              Read 128-byte record
  778.          LTR   R15,R15                  Check for EOF
  779.          BNZ   GSEOF                    Use error code in GETSTR
  780.          CLI   OPRCODE,C'V'             Conversion wanted?
  781.          BNE   BINDNXT                  No, continue
  782.          BAL   R14,HQXPUT               Write data block
  783.          BAL   R14,CRCCALC              Include in CRC
  784. BINDNXT  BCT   R4,BINDLP                Repeat for all pieces
  785. BINDLEFT LTR   R3,R3               Any bytes left?
  786.          BNP   BINDEND             No, check for writing CRC
  787.          BAL   R14,GETLINE         Read 128-byte record
  788.          LTR   R15,R15             Check for EOF
  789.          BNZ   GSEOF               Use error code in GETSTR
  790.          CLI   OPRCODE,C'V'        Conversion wanted?
  791.          BNE   BINDEND             No, skip writing data
  792.          LR    R0,R3               Use remaining bytes length
  793.          BAL   R14,HQXPUT          Write data block
  794.          BAL   R14,CRCCALC         Include in CRC
  795. BINDEND  CLI   OPRCODE,C'V'        Conversion wanted?
  796.          BNE   BINRSC              No, ready for resource fork
  797.          LA    R0,2                Include X'0000' in CRC
  798.          LA    R1,=H'0'
  799.          BAL   R14,CRCCALC
  800.          LA    R0,2                R0 = size of CRC
  801.          LA    R1,CRCVAL           R1 -> CRC
  802.          BAL   R14,HQXPUT          Output data fork CRC
  803. BINRSC   EQU   *                   Process BinHex resource fork
  804.          ICM   R3,B'1111',HDRSCLN  Get resource fork length
  805.          LR    R4,R3               R4 = number of 128-byte records
  806.          SRL   R4,7
  807.          LR    R5,R4               R5 = bytes for all records
  808.          SLL   R5,7
  809.          SR    R3,R5               R3 = bytes left over
  810.          LA    R0,128              R0 = byte count
  811.          L     R1,=A(READBUFF)     R1 -> buffer
  812.          XC    CRCVAL(2),CRCVAL    Reset CRC
  813.          LTR   R4,R4               Any entire records to read?
  814.          BNP   BINRLEFT            No, skip loop
  815. BINRLP   EQU   *                   Loop to read 128-byte records
  816.          BAL   R14,GETLINE              Read 128-byte record
  817.          LTR   R15,R15                  Check for EOF
  818.          BNZ   GSEOF                    Use error code in GETSTR
  819.          CLI   OPRCODE,C'V'             Conversion wanted?
  820.          BNE   BINRNXT                  No, continue
  821.          BAL   R14,HQXPUT               Write resource block
  822.          BAL   R14,CRCCALC              Include in CRC
  823. BINRNXT  BCT   R4,BINRLP                Repeat for all pieces
  824. BINRLEFT LTR   R3,R3               Any bytes left?
  825.          BNP   BINREND             No, check for writing CRC
  826.          BAL   R14,GETLINE         Read 128-byte record
  827.          LTR   R15,R15             Check for EOF
  828.          BNZ   GSEOF               Use error code in GETSTR
  829.          CLI   OPRCODE,C'V'        Conversion wanted?
  830.          BNE   BINREND             No, skip writing data
  831.          LR    R0,R3               Use remaining bytes length
  832.          BAL   R14,HQXPUT          Write resource block
  833.          BAL   R14,CRCCALC         Include in CRC
  834. BINREND  CLI   OPRCODE,C'V'        Conversion wanted?
  835.          BNE   RSCDONE             No, join common end code
  836.          LA    R0,2                Include X'0000' in CRC
  837.          LA    R1,=H'0'
  838.          BAL   R14,CRCCALC
  839.          LA    R0,2                R0 = size of CRC
  840.          LA    R1,CRCVAL           R1 -> CRC
  841.          BAL   R14,HQXPUT          Output data fork CRC
  842.          L     R0,=F'-1'           R0 = -1 for cleanup
  843.          BAL   R14,HQXPUT          HQXPUT final cleanup call
  844. *                                  append final colon
  845.          L     R1,WRLEN            Room for colon in buffer?
  846.          C     R1,=F'64'           Yes, if length < 64
  847.          BL    BINADDC
  848.          BAL   R14,HQXLINE         Else write 64 bytes to file
  849.          XC    WRLEN(4),WRLEN        and reset length
  850. BINADDC  L     R2,WRLEN            R2 = no. of bytes in WRITBUFF
  851.          L     R1,=A(WRITBUFF)     R1 -> start of buffer
  852.          LA    R3,0(R1,R2)         R3 -> next location
  853.          MVI   0(R3),C':'          Store ending colon
  854.          LA    R2,1(R2)            Store new length
  855.          ST    R2,WRLEN
  856.          BAL   R14,HQXLINE         Output final line
  857.          B     RSCDONE             Join common code
  858.          EJECT
  859. *
  860. * HQXPUT - Apply HQX compression algorithm to binary data, and call
  861. *          HQXEXP to expand up to 48 bytes of binary to up to 64 bytes
  862. *          of printable characters.  At entry R0 is the number of bytes
  863. *          to process, and R1 contains their address.  HQXPUT is called
  864. *          with R0 < 0 for final cleanup.
  865. *
  866. HQXPUT   DS    0H
  867.          LTR   R0,R0               Just return if zero bytes
  868.          BZR   R14
  869.          STM   R0,R15,HPUTSAVE     Save registers
  870.          LR    R2,R0               R2 = count for BCT
  871. *                                  R1 -> current byte
  872.          SR    R3,R3               R3 = current CMPMODE
  873.          IC    R3,CMPMODE
  874.          SR    R4,R4               R4 = current HCMPCHAR
  875.          IC    R4,HCMPCHAR
  876.          SR    R5,R5               R5 = current CMPCOUNT
  877.          IC    R5,CMPCOUNT
  878.          L     R9,EXPLEN           R9 = output length
  879.          L     R8,=A(EXPBUFF)      R8 -> next output byte
  880.          LA    R8,0(R8,R9)
  881.          LTR   R2,R2               Ready for main loop if R2 > 0
  882.          BP    HPUTLP
  883. *                                  Else final cleanup call
  884.          CLI   CMPMODE,0           Done if mode = 0
  885.          BE    HCLEND
  886.          SR    R1,R1               Set byte address to 0
  887.          LA    R2,1                Set BCT count to 1
  888.          SR    R6,R6               Get character in R6
  889.          IC    R6,HCMPCHAR
  890.          SR    R7,R7               Get count in R7
  891.          IC    R7,CMPCOUNT
  892.          B     HOUT                Enter loop at output code
  893.          SPACE
  894. HPUTLP   EQU   *                   Loop to process each character
  895.          LTR   R3,R3                    Check for mode 1
  896.          BNZ   HPUT1
  897. *                                       Else mode 0:
  898. HPUT0    EQU   *                        Mode 0: initial mode
  899.          IC    R4,0(R1)                 Save current character
  900.          LA    R5,1                     Set count to 1
  901.          LA    R3,1                     Set mode to 1
  902.          B     HPUTNXT                  Ready for next byte
  903.          SPACE
  904. HPUT1    EQU   *                        Mode 1: checking for comp.
  905.          CLM   R4,B'0001',0(R1)         New char. the same as prev.?
  906.          BNE   HDIFF                    No, go handle
  907.          LA    R5,1(R5)                 Increment count
  908.          C     R5,=F'255'               Done if < 255
  909.          BL    HPUTNXT
  910.          LR    R6,R4                    R6 = char. to output
  911.          LR    R7,R5                    R7 = count
  912.          SR    R3,R3                    Mode = 0 (no prev. char.)
  913.          B     HOUT
  914.          SPACE
  915. HDIFF    EQU   *                        New char. not same as prev.
  916. *                                       Output previous character
  917.          LR    R6,R4                    R6 = char. to output
  918.          LR    R7,R5                    R7 = count to output
  919.          IC    R4,0(R1)                 Save current character
  920.          LA    R5,1                     Set count to 1
  921. HOUT     EQU   *                        Char. in R6, count in R7
  922.          LTR   R7,R7                    Done if count = 0
  923.          BZ    HPUTNXT
  924.          STC   R6,0(R8)                 Append byte to buffer
  925.          LA    R8,1(R8)                 Increment pointer
  926.          LA    R9,1(R9)                 Increment count
  927.          C     R9,=F'48'                Buffer full?
  928.          BL    HOUT2                    No, check for X'90'
  929.          ST    R9,EXPLEN                Store length for HQXEXP
  930.          BAL   R14,HQXEXP               Call expansion routine
  931.          L     R8,=A(EXPBUFF)           Reset pointer
  932.          SR    R9,R9                    Reset count
  933. HOUT2    CLM   R6,B'0001',=X'90'        Is character X'90'?
  934.          BNE   HOUT3                    No, check for repetition
  935.          MVI   0(R8),0                  Append zero byte
  936.          LA    R8,1(R8)                 Increment pointer
  937.          LA    R9,1(R9)                 Increment count
  938.          C     R9,=F'48'                Buffer full?
  939.          BL    HOUT3                    No, check for repetition
  940.          ST    R9,EXPLEN                Store length for HQXEXP
  941.          BAL   R14,HQXEXP               Call expansion routine
  942.          L     R8,=A(EXPBUFF)           Reset pointer
  943.          SR    R9,R9                    Reset count
  944. HOUT3    BCTR  R7,0                     Decrement count
  945.          C     R7,=F'2'                 If < 2 more, output w/o comp.
  946.          BL    HOUT
  947. *                                       else output X'90', count
  948.          MVI   0(R8),X'90'              Append X'90'
  949.          LA    R8,1(R8)                 Increment pointer
  950.          LA    R9,1(R9)                 Increment count
  951.          C     R9,=F'48'                Buffer full?
  952.          BL    HOUT4                    No, ready for count
  953.          ST    R9,EXPLEN                Store length for HQXEXP
  954.          BAL   R14,HQXEXP               Call expansion routine
  955.          L     R8,=A(EXPBUFF)           Reset pointer
  956.          SR    R9,R9                    Reset count
  957. HOUT4    LA    R7,1(R7)                 Restore original byte count
  958.          STC   R7,0(R8)                 Append byte count
  959.          LA    R8,1(R8)                 Increment pointer
  960.          LA    R9,1(R9)                 Increment count
  961.          C     R9,=F'48'                Buffer full?
  962.          BL    HPUTNXT                  No, all done
  963.          ST    R9,EXPLEN                Store length for HQXEXP
  964.          BAL   R14,HQXEXP               Call expansion routine
  965.          L     R8,=A(EXPBUFF)           Reset pointer
  966.          SR    R9,R9                    Reset count
  967. HPUTNXT  LA    R1,1(R1)                 R1 -> next byte
  968.          BCT   R2,HPUTLP                Decrement count and repeat
  969.          L     R2,HPUTSAVE         Get original R0
  970.          LTR   R2,R2               If <0, finish cleanup
  971.          BM    HCLEND
  972.          ST    R9,EXPLEN           Store EXPBUFF length
  973.          STC   R3,CMPMODE          Store CMPMODE
  974.          STC   R4,HCMPCHAR         Store HCMPCHAR
  975.          STC   R5,CMPCOUNT         Store CMPCOUNT
  976. HPUTRTN  LM    R0,R15,HPUTSAVE     Restore registers
  977.          BR    R14                 Return to caller
  978.          SPACE
  979. HCLEND   EQU   *                   Output bytes left in EXPBUFF
  980.          ST    R9,EXPLEN           Store length for HQXEXP
  981.          C     R9,=F'48'           Check for zeros to add
  982.          BE    HNOZERO             None if buffer full
  983.          MVI   0(R8),0             Add one zero
  984.          LA    R8,1(R8)
  985.          C     R9,=F'47'           Room for another?
  986.          BE    HNOZERO             No, ready to output
  987.          MVI   0(R8),0             Add another null
  988. HNOZERO  BAL   R14,HQXEXP          Call expansion routine
  989.          B     HPUTRTN             Ready to return
  990.          SPACE
  991. HPUTSAVE DS    8D                  Local save area
  992.          EJECT
  993. *
  994. * HQXEXP - Expand data in EXPBUFF to 6 bits in each byte.  The length
  995. *          is used from EXPLEN, and is assumed to not exceed 48.
  996. *          Expanded data is translated and moved to WRITBUFF.  HQXLINE
  997. *          is called to output WRITBUFF as necessary.
  998. *
  999. HQXEXP   STM   R0,R15,HEXPSAVE     Save registers
  1000.          SR    R2,R2               R2, R3 = size of EXPBUFF data
  1001.          L     R3,EXPLEN
  1002.          LTR   R3,R3               If zero, just return
  1003.          BZ    HEXPRTN
  1004.          D     R2,=F'3'            Divide to get 3-byte pieces
  1005.          LTR   R2,R2               Check for any remainder
  1006.          BZ    HNORM               If none, keep count
  1007.          LA    R0,1(R3)            Piece count = quotient+1
  1008.          SLL   R3,2                Length = quotient*4
  1009.          LA    R3,1(R2,R3)            + remainder + 1
  1010.          LR    R2,R0               Copy piece count to R2
  1011.          B     HCNT                Continue with these counts
  1012.          SPACE
  1013. HNORM    LR    R2,R3               R2 = count of pieces for BCT
  1014.          SLL   R3,2                R3 = output length (count*4)
  1015. HCNT     L     R4,=A(EXPBUFF)      R4 -> start of input
  1016.          LA    R5,HEXPBUFF         R5 -> start of output
  1017. HEXPLP   EQU   *                   Loop to expand pieces
  1018.          ICM   R7,B'1110',0(R4)         Get all 24 bits in R7
  1019.          SR    R6,R6                    Get first 6 bits in R6
  1020.          SLDL  R6,6
  1021.          STC   R6,0(R5)                 Store first result byte
  1022.          SR    R6,R6                    Repeat for 2nd byte
  1023.          SLDL  R6,6
  1024.          STC   R6,1(R5)
  1025.          SR    R6,R6                    Repeat for 3rd byte
  1026.          SLDL  R6,6
  1027.          STC   R6,2(R5)
  1028.          SR    R6,R6                    Repeat for 4th byte
  1029.          SLDL  R6,6
  1030.          STC   R6,3(R5)
  1031.          LA    R4,3(R4)                 Increment input pointer
  1032.          LA    R5,4(R5)                 Increment output pointer
  1033.          BCT   R2,HEXPLP                Repeat for piece count
  1034.          BCTR  R3,0                Get length-1 for execute
  1035.          L     R4,=A(BINTOASC)     R4 -> binary-to-ASCII table
  1036.          EX    R3,HEXPTR           Convert binary to ASCII
  1037.          L     R4,FRASCADR         R4 -> ASCII-to-EBCDIC table
  1038.          EX    R3,HEXPTR           Convert ASCII to EBCDIC
  1039.          LA    R3,1(R3)            Restore original length
  1040.          LA    R2,HEXPBUFF         R2 -> first byte
  1041.          LA    R5,64               R5 = bytes left in WRITBUFF
  1042.          S     R5,WRLEN
  1043.          CR    R3,R5               Will all bytes fit?
  1044.          BNH   HEXWRCPY            Yes, copy into buffer
  1045.          L     R4,=A(WRITBUFF)     R4 -> next output location
  1046.          A     R4,WRLEN
  1047.          BCTR  R5,0                R5 = length for EX
  1048.          EX    R5,HEXPMVC          Fill output buffer
  1049.          LA    R4,64               Store new length
  1050.          ST    R4,WRLEN
  1051.          BAL   R14,HQXLINE         Output buffer to file
  1052.          XC    WRLEN(4),WRLEN      Reset length
  1053.          LA    R5,1(R5)            Get actual count moved
  1054.          SR    R3,R5               R3 = bytes still to move
  1055.          LA    R2,0(R2,R5)         R2 -> next byte to move
  1056. HEXWRCPY L     R4,=A(WRITBUFF)     R4 -> next output location
  1057.          A     R4,WRLEN
  1058.          BCTR  R3,0                R3 = length for EX
  1059.          EX    R3,HEXPMVC          Move bytes to output buffer
  1060.          L     R4,WRLEN            Update buffer size
  1061.          LA    R4,1(R3,R4)
  1062.          ST    R4,WRLEN
  1063.          C     R4,=F'64'           Is buffer full now?
  1064.          BNE   HEXPRTN             No, ready to return
  1065.          BAL   R14,HQXLINE         Output full buffer
  1066.          XC    WRLEN(4),WRLEN      Reset buffer length
  1067. HEXPRTN  LM    R0,R15,HEXPSAVE     Restore registers
  1068.          BR    R14                 Return to caller
  1069.          SPACE
  1070. HEXPSAVE DS    8D                  Local save area
  1071. HEXPBUFF DS    8D                  Local buffer for expansion
  1072. HEXPTR   TR    HEXPBUFF(*-*),0(R4)
  1073. HEXPMVC  MVC   0(*-*,R4),0(R2)
  1074.          EJECT
  1075. *
  1076. * HQXLINE - Write contents of WRITBUFF to output file.  The current
  1077. *           length of the data in WRITBUFF is given in WRITLEN.
  1078. *           Returns to caller if no error; otherwise types an error
  1079. *           message and returns directly to CMS.
  1080. *
  1081. HQXLINE  DS    0H
  1082.          STM   R0,R15,HQXLSAVE     Save registers
  1083.          L     R2,WRITEM           Increment line number
  1084.          LA    R2,1(R2)
  1085.          ST    R2,WRITEM
  1086.          OI    FLAGS,WROPEN        Remember file is open
  1087.          MVC   WRBUFLTH(4),WRLEN   Set line length from buffer size
  1088.          LA    R1,OUTPLIST         R1 -> PLIST
  1089.          L     R15,AWRBUF          R15 -> WRBUF entry
  1090.          BALR  R14,R15             Call WRBUF
  1091.          BZ    HQXLRET             If ok, ready to return
  1092.          LR    R2,R15              Copy error code to R2
  1093.          DMSERR LET=S,NUM=105,                                         X
  1094.                TEXT='Error ''..'' writing file ''....................''X
  1095.                 on disk',SUB=(DEC,(R2),CHAR8A,OFN),RENT=NO
  1096.          LA    R2,100(R2)          Set RC = 1nn
  1097.          ST    R2,RTNCODE          Set code to return
  1098.          B     CMSRTN              Direct return to CMS
  1099.          SPACE
  1100. HQXLRET  LM    R0,R15,HQXLSAVE     Restore registers
  1101.          BR    R14                 Return to caller
  1102.          SPACE
  1103. HQXLSAVE DS    8D                  Local save area
  1104.          EJECT
  1105. *
  1106. * GETSTR - Fill buffer with bytes from input file.  At entry,
  1107. *          R0 contains the buffer size and R1 contains the buffer
  1108. *          address.  If any errors occur, GETSTR generates an
  1109. *          error message and returns to CMS.
  1110. *
  1111. GETSTR   DS    0H
  1112.          STM   R0,R15,GSSAVE       Save registers
  1113.          LR    R4,R0               R4 = buffer size
  1114.          LR    R5,R1               R5 -> buffer
  1115. GSAGAIN  LTR   R4,R4               Buffer size = 0?
  1116.          BZ    GSRTN               If so, just return
  1117.          CLI   CMPCNT,0            Compressed data to return?
  1118.          BNE   GSUSECMP            Yes, go use it
  1119.          L     R6,BINLEN           R6 = count of bytes left
  1120.          L     R7,=A(BINBUFF)      R7 -> next byte
  1121.          A     R7,BINOFF
  1122.          LTR   R6,R6               Any bytes left?
  1123.          BP    GSUSEBIN            Yes, go use them
  1124.          MVC   GSPREV(1),BINLAST   Save last byte from current line
  1125.          BAL   R14,GTBINLIN        Read more binary data
  1126.          LTR   R15,R15             Any error?
  1127.          BZ    GSAGAIN             No, use data
  1128.          B     GSEOF               Else return EOF
  1129.          SPACE
  1130. GSUSEBIN EQU   *                   Process data in BINBUFF
  1131.          LA    R1,0(R6,R7)         R1 -> past last byte
  1132.          LR    R3,R6               R3 = length-1 for TRT
  1133.          BCTR  R3,0
  1134.          L     R8,=A(CMPTAB)       R8 -> TRT table
  1135.          EX    R3,CMPTRT           Scan for X'90' in BINBUFF
  1136.          SR    R1,R7               R1 = length before X'90'
  1137.          BZ    GSCMPINI            If none, set up for compression
  1138.          NI    FLAGS,255-X90DATA   X90 data byte no longer current
  1139.          CR    R1,R4               Longer than needed?
  1140.          BNH   GSMVDATA            No, keep length
  1141.          LR    R1,R4               Else reduce to length needed
  1142. GSMVDATA BCTR  R1,0                Decrement length for EX
  1143.          EX    R1,DATAMVC          Move data to caller's buffer
  1144.          LA    R1,1(R1)            Restore actual length
  1145.          SR    R4,R1               Decrement buffer size
  1146.          LA    R5,0(R1,R5)         Increment buffer address
  1147.          L     R2,BINLEN           Decrement binary length
  1148.          SR    R2,R1
  1149.          ST    R2,BINLEN
  1150.          L     R2,BINOFF           Increment binary offset
  1151.          AR    R2,R1
  1152.          ST    R2,BINOFF
  1153.          B     GSAGAIN             Check for more to do
  1154.          SPACE
  1155. GSCMPINI EQU   *                   R7 -> X'90'
  1156. *                                  Get compression character
  1157.          TM    FLAGS,X90DATA       Have character from last X'90'?
  1158.          BO    USEX90              Yes, use it
  1159.          L     R1,BINOFF           Is X'90' at start of line
  1160.          LTR   R1,R1               If so, use byte from previous line
  1161.          BZ    USEPREV
  1162.          LR    R1,R7               Else use previous byte on line
  1163.          BCTR  R1,0                R1 -> byte to use
  1164.          B     STCMPCHR
  1165.          SPACE
  1166. USEX90   LA    R1,X90CHAR          R1 -> byte from last X90
  1167.          B     STCMPCHR
  1168.          SPACE
  1169. USEPREV  LA    R1,GSPREV           R1 -> byte to use
  1170. STCMPCHR MVC   CMPCHAR(1),0(R1)    Store byte to replicate
  1171.          OI    FLAGS,X90DATA       Set flag for X90 data
  1172.          MVC   X90CHAR(1),0(R1)    Save X90 data byte
  1173.          C     R6,=F'1'            Is count available after X'90'?
  1174.          BNH   GSRDCNT             No, go read it
  1175.          MVC   CMPCNT(1),1(R7)     Store compression count
  1176.          L     R2,BINOFF           Increment binary offset
  1177.          LA    R2,2(R2)
  1178.          ST    R2,BINOFF
  1179.          L     R2,BINLEN           Decrement binary length
  1180.          BCTR  R2,0
  1181.          BCTR  R2,0
  1182.          ST    R2,BINLEN
  1183.          B     CHKCMP              Ready to check what we have
  1184.          SPACE
  1185. GSRDCNT  BAL   R14,GTBINLIN        Read more binary data
  1186.          LTR   R15,R15             Any error?
  1187.          BNZ   GSEOF               Yes, return EOF
  1188.          L     R6,BINLEN           Update R6, R7 for new read
  1189.          L     R7,=A(BINBUFF)
  1190.          A     R7,BINOFF
  1191.          MVC   CMPCNT(1),0(R7)     Store compression count
  1192.          L     R2,BINOFF           Increment binary offset
  1193.          LA    R2,1(R2)
  1194.          ST    R2,BINOFF
  1195.          L     R2,BINLEN           Decrement binary length
  1196.          BCTR  R2,0
  1197.          ST    R2,BINLEN
  1198. CHKCMP   CLI   CMPCNT,0            New count = 0?
  1199.          BNE   GSDECCMP            No, adjust count to be length
  1200.          MVI   X90CHAR,X'90'       Data byte is now X'90'
  1201.          MVI   0(R5),X'90'         Return X'90'
  1202.          BCTR  R4,0                Decrement buffer size
  1203.          LA    R5,1(R5)            Increment buffer pointer
  1204.          B     GSAGAIN             See if more to do
  1205.          SPACE
  1206. GSDECCMP SR    R1,R1               Get count in R1
  1207.          IC    R1,CMPCNT
  1208.          BCTR  R1,0                Decrement to get replication count
  1209.          STC   R1,CMPCNT
  1210.          LTR   R1,R1               If zero, start again
  1211.          BNP   GSAGAIN
  1212. GSUSECMP SR    R1,R1               R1 = compression count
  1213.          IC    R1,CMPCNT
  1214.          LR    R2,R1               Save in R2
  1215.          CR    R1,R4               Count bigger than buffer size?
  1216.          BNH   CMPCPY              No, keep count
  1217.          LR    R1,R4               Else reduce to buffer size
  1218. CMPCPY   SR    R2,R1               R2 = remaining count
  1219.          STC   R2,CMPCNT           Store remaining count
  1220.          LR    R8,R1               Save count in R8
  1221.          LR    R0,R5               R0 -> destination
  1222. *                                  R1 = destination length
  1223.          SR    R2,R2               R2 -> source (none)
  1224.          SR    R3,R3               R3 = source length (zero)
  1225.          ICM   R3,B'1000',CMPCHAR  Pad char. = compression char.
  1226.          MVCL  R0,R2               Store duplicated characters
  1227.          SR    R4,R8               Decrement buffer size
  1228.          LA    R5,0(R5,R8)         Increment buffer pointer
  1229.          B     GSAGAIN             Check for more to do
  1230.          SPACE
  1231. GSRTN    LM    R0,R15,GSSAVE       Restore registers
  1232.          BR    R14                 Return to caller
  1233.          SPACE
  1234. GSEOF    DMSERR NUM=6,LET=E,                                           X
  1235.                TEXT='Unexpected end-of-file reading ''.................X
  1236.                ...''',SUB=(CHAR8A,IFN)
  1237.          MVI   RTNCODE+3,36        CMS RC = 36
  1238.          B     CMSRTN
  1239.          SPACE
  1240. GSSAVE   DS    8D                  Local save area
  1241. CMPTRT   TRT   0(*-*,R7),0(R8)     TRT for X'90'
  1242. DATAMVC  MVC   0(*-*,R5),0(R7)     Move binary data to buffer
  1243. GSPREV   DS    1X                  Last byte from previous line
  1244. X90CHAR  DS    1X                  Data byte for last X'90'
  1245.          EJECT
  1246. *
  1247. * GTBINLIN - Convert data in READBUFF to binary data in BINBUFF
  1248. *            (HQX files only).  The length is returned in BINLEN.
  1249. *            Returns R15=0 (ok) or R15=12 (eof).
  1250. *
  1251. GTBINLIN DS    0H
  1252.          STM   R0,R15,GBSAVE       Save registers
  1253. GBAGAIN  BAL   R14,GETLINE         Get more data from file
  1254.          ST    R15,GBSAVE+60       Store return code
  1255.          LTR   R15,R15             Return if non-zero
  1256.          BNZ   GBRET
  1257.          XC    BINOFF(4),BINOFF    Reset offset for reading result
  1258.          L     R1,=A(READBUFF)     R1 -> first byte
  1259.          A     R1,RDOFF
  1260.          L     R2,RDLGTH           R2 = length
  1261.          L     R3,=A(BINBUFF)      R3 -> output buffer
  1262.          SR    R4,R4               R4 = output length
  1263.          LA    R5,CVCNT0           R5 = addr. for checking zero bits
  1264. GBINILP  EQU   *                   Loop until no bits left over or EOF
  1265.          LTR   R2,R2                    Any bytes left?
  1266.          BZ    GBEND                    No, ready to return
  1267.          C     R5,BINXTADR              No bits left over?
  1268.          BE    GBGROUP                  Yes, do groups of bytes
  1269.          BAL   R14,CVTBYTE              Convert next byte
  1270.          STC   R0,0(R3)                 Store output byte
  1271.          LA    R3,1(R3)                 Increment address
  1272.          LA    R4,1(R4)                 Increment length
  1273.          LA    R1,1(R1)                 Increment pointer
  1274.          BCTR  R2,0                     Decrement length
  1275.          B     GBINILP                  Repeat
  1276.          SPACE
  1277. * Process groups of 8 input byte to get 6 binary bytes
  1278. GBGROUP  LR    R5,R2               Get count of groups
  1279.          SRL   R5,3                = byte count/8
  1280.          LTR   R5,R5               Any groups?
  1281.          BZ    GBFIN               No, loop for any bytes left
  1282.          SR    R8,R8               R8 = 0 for IC
  1283.          LA    R0,1                R0 = 1 for increments
  1284. GBGRLP   EQU   *                   Loop to process groups
  1285.          LA    R9,8                     R9 = byte count for loop
  1286. GBG1LP   EQU   *                        Loop for 1 group
  1287.          IC    R8,0(R1)                      Get new byte
  1288.          SLDL  R6,6                          Make room for new bits
  1289.          OR    R7,R8                         OR-in bits
  1290.          AR    R1,R0                         R1 -> next byte
  1291.          BCT   R9,GBG1LP                     Repeat for 8 bytes
  1292.          S     R2,=F'8'                 Decrement bytes left
  1293.          STCM  R6,B'0011',0(R3)         Store result bytes
  1294.          STCM  R7,B'1111',2(R3)
  1295.          LA    R3,6(R3)            Increment output address
  1296.          LA    R4,6(R4)            Increment output length
  1297.          BCT   R5,GBGRLP           Loop for all groups
  1298. * Loop to process any remaining bytes
  1299. GBFIN    LTR   R2,R2               Any bytes left?
  1300.          BZ    GBEND               No, ready to return
  1301. GBENDLP  EQU   *                   Loop to process remaining bytes
  1302.          BAL   R14,CVTBYTE              Convert next byte
  1303.          LTR   R0,R0                    Result byte returned?
  1304.          BM    GBENDNXT                 No, skip saving byte
  1305.          STC   R0,0(R3)                 Store output byte
  1306.          LA    R3,1(R3)                 Increment address
  1307.          LA    R4,1(R4)                 Increment length
  1308. GBENDNXT LA    R1,1(R1)                 Increment pointer
  1309.          BCT   R2,GBENDLP
  1310.          SPACE
  1311. * Return to caller
  1312. GBEND    LTR   R4,R4               Non-zero length to return?
  1313.          BZ    GBAGAIN             No, read next line
  1314.          ST    R4,BINLEN           Store output length
  1315.          L     R3,=A(BINBUFF)      R4 -> last byte
  1316.          LA    R3,0(R3,R4)
  1317.          BCTR  R3,0
  1318.          MVC   BINLAST(1),0(R3)    Save in case part of compression
  1319. GBRET    LM    R0,R15,GBSAVE       Restore registers, RC in R15
  1320.          BR    R14
  1321.          SPACE
  1322. GBSAVE   DS    8D                  Local save area
  1323.          EJECT
  1324. *
  1325. * CVTBYTE - Read next byte using address in R1 and any left over bits
  1326. *           in BINEXTRA.  Return a new byte in R0, and set BINEXTRA
  1327. *           and BINXTADR as appropriate.  Return R0=-1 if more bits
  1328. *           are needed to make a byte.
  1329. *
  1330. CVTBYTE  DS    0H
  1331.          STM   R0,R15,CVSAVE       Save registers and RC
  1332.          L     R2,BINXTADR         Get addr. for processing
  1333.          BR    R2                  Branch for left over bits
  1334.          SPACE
  1335. CVCNT0   EQU   *                   No bits left over
  1336.          IC    R3,0(R1)            New bits in R3
  1337.          LA    R1,CVCNT6           Set 6 bits left over
  1338.          ST    R1,BINXTADR
  1339.          L     R0,=F'-1'           Return -1 in R0
  1340.          STC   R3,BINEXTRA         Store left over bits
  1341.          B     CVRTN
  1342.          SPACE
  1343. CVCNT6   EQU   *                   6 bits left from last time
  1344.          SR    R2,R2               Left over bits in R2
  1345.          IC    R2,BINEXTRA
  1346.          IC    R3,0(R1)            New bits in R3
  1347.          SLL   R3,26               Make new bits most significant
  1348.          SLDL  R2,2                Get new byte in R2
  1349.          SRL   R3,28               Get left over bits in R3
  1350.          LA    R1,CVCNT4           Set 4 bits left over
  1351.          ST    R1,BINXTADR
  1352.          LR    R0,R2               Return byte in R0
  1353.          STC   R3,BINEXTRA         Store left over bits
  1354.          B     CVRTN               Ready to return
  1355.          SPACE
  1356. CVCNT4   EQU   *                   4 bits left from last time
  1357.          SR    R2,R2               Left over bits in R2
  1358.          IC    R2,BINEXTRA
  1359.          IC    R3,0(R1)            New bits in R3
  1360.          SLL   R3,26               Make new bits most significant
  1361.          SLDL  R2,4                Get new byte in R2
  1362.          SRL   R3,30               Get left over bits in R3
  1363.          LA    R1,CVCNT2           Set 2 bits left over
  1364.          ST    R1,BINXTADR
  1365.          LR    R0,R2               Return byte in R0
  1366.          STC   R3,BINEXTRA         Store left over bits
  1367.          B     CVRTN               Ready to return
  1368.          SPACE
  1369. CVCNT2   EQU   *                   2 bits left from last time
  1370.          SR    R2,R2               Left over bits in R2
  1371.          IC    R2,BINEXTRA
  1372.          IC    R3,0(R1)            New bits in R3
  1373.          SLL   R3,26               Make new bits most significant
  1374.          SLDL  R2,6                Get new byte in R2
  1375.          LA    R1,CVCNT0           Set 0 bits left over
  1376.          ST    R1,BINXTADR
  1377.          LR    R0,R2               Return byte in R0
  1378. *        B     CVRTN               Ready to return
  1379.          SPACE
  1380. CVRTN    LM    R1,R15,CVSAVE+4     Restore all but result in R0
  1381.          BR    R14                 Return to caller
  1382.          SPACE
  1383. CVSAVE   DS    8D                  Local save area
  1384.          EJECT
  1385. *
  1386. * GETLINE - Read the next line of the input file into READBUFF.
  1387. *           The length is returned in RDLGTH and the starting
  1388. *           offset is returned in RDOFF.  For HQX files, data is
  1389. *           returned between a starting colon in column one of a
  1390. *           line, and an ending colon.  Also, data is translated
  1391. *           to six-bit binary.
  1392. *           Return R15=0 (ok) or R15=12 (eof).
  1393. *
  1394. GETLINE  DS    0H
  1395.          STM   R0,R15,GLSAVE       Save registers
  1396. GLAGAIN  TM    FLAGS,HQXEOF        EOF set from last time?
  1397.          BO    GLEOFRET            Yes, return eof
  1398.          L     R1,RDITEM           Increment line number
  1399.          LA    R1,1(R1)
  1400.          ST    R1,RDITEM
  1401.          XC    RDOFF(4),RDOFF      Reset read offset
  1402.          OI    FLAGS,RDOPEN        Remember input file is open
  1403.          LA    R1,INPLIST          R1 -> PLIST
  1404.          L     R15,ARDBUF          R15 -> RDBUF entry
  1405.          BALR  R14,R15             Call RDBUF
  1406.          ST    R15,GLSAVE+60       Return RC in R15
  1407.          BZ    GLRDOK              RC 0 is normal
  1408.          C     R15,=F'12'          RC 12 is eof
  1409.          BE    GLRET
  1410. *                                  Else unexpected error
  1411.          LR    R2,R15              Copy error code to R2
  1412.          DMSERR LET=S,NUM=104,                                         X
  1413.                TEXT='Error ''..'' reading file ''....................''X
  1414.                 from disk',SUB=(DEC,(R2),CHAR8A,IFN),RENT=NO
  1415.          LA    R2,100(R2)          Set RC = 1nn
  1416.          ST    R2,RTNCODE
  1417.          B     CMSRTN              Direct return to CMS
  1418.          SPACE
  1419. GLRDOK   CLC   RDLGTH(4),=F'0'     Any bytes read?
  1420.          BE    GLAGAIN             No (very strange); try again
  1421.          L     R1,CHRTOTAL         Increment character count
  1422.          A     R1,RDLGTH
  1423.          ST    R1,CHRTOTAL
  1424.          TM    FLAGS,MACBIN        If reading MacBinary, all done
  1425.          BO    GLRET
  1426. * For HQX file, adjust length to delete trailing blanks
  1427.          L     R1,RDLGTH           R1 = count for BCT
  1428.          L     R2,=A(READBUFF)     R2 -> last byte
  1429.          LA    R2,0(R1,R2)         R2 -> last byte
  1430.          BCTR  R2,0
  1431. GLTRLOOP EQU   *                   Loop to truncate blanks
  1432.          CLI   0(R2),C' '               Found non-blank?
  1433.          BNE   GLTREND                  Yes, done
  1434.          BCTR  R2,0                     R2 -> previous byte
  1435.          BCT   R1,GLTRLOOP              Repeat for line length
  1436.          B     GLAGAIN             If all blank, read next line
  1437.          SPACE
  1438. GLTREND  ST    R1,RDLGTH           Store adjusted line length
  1439. * For HQX file, handle initial colon
  1440.          TM    FLAGS,HQXCOLON      Colon in previous line?
  1441.          BO    GLHQXCNT            Yes, continue
  1442.          L     R2,=A(READBUFF)     Does this line start with colon?
  1443.          CLI   0(R2),C':'
  1444.          BNE   GLAGAIN             No, try again
  1445.          OI    FLAGS,HQXCOLON      Remember have found colon
  1446.          BCTR  R1,0                Decrement line length
  1447.          LTR   R1,R1               Zero now?
  1448.          BZ    GLAGAIN             Yes, get next line
  1449.          ST    R1,RDLGTH           Store new length
  1450.          LA    R2,1                Initial offset = 1
  1451.          ST    R2,RDOFF
  1452. * For HQX file, check for ending colon or invalid character
  1453. GLHQXCNT L     R3,=A(READBUFF)     R3 -> first byte
  1454.          A     R3,RDOFF
  1455.          L     R4,RDLGTH           R4 = length
  1456.          BCTR  R4,0                Decrement length for EX
  1457.          SR    R1,R1               Initialize R1 before TRT
  1458.          L     R5,=A(VALIDTAB)     R5 -> TRT table
  1459.          EX    R4,HQXTRT           Scan for invalid character
  1460.          BZ    GLHQXTR             Ready to translate if none
  1461.          OI    FLAGS,HQXEOF        Remember EOF for HQX file
  1462.          MVC   EOFCHAR(1),0(R1)    Save character we stopped at
  1463.          LA    R2,1(R1)            Save character position in line
  1464.          L     R4,=A(READBUFF)
  1465.          SR    R2,R4
  1466.          ST    R2,EOFPOS
  1467.          SR    R1,R3               R1 = new length
  1468.          ST    R1,RDLGTH           Store new length
  1469.          BNP   GLEOFRET            Return EOF if not positive
  1470. * For HQX file, translate EBCDIC to 6-bit binary
  1471. GLHQXTR  L     R1,RDLGTH           R1 = length
  1472.          BCTR  R1,0                Decrement for EX
  1473.          L     R2,=A(READBUFF)     R2 -> first byte
  1474.          A     R2,RDOFF
  1475.          L     R3,TOASCADR         R3 -> EBCDIC-to-ASCII table
  1476.          EX    R1,GLTR             Translate data to ASCII
  1477.          L     R3,=A(ASCTOBIN)     R3 -> ASCII-to-binary table
  1478.          EX    R1,GLTR             Translate ASCII to binary
  1479. * Return to caller
  1480. GLRET    LM    R0,R15,GLSAVE       Restore registers, RC in R15
  1481.          BR    R14
  1482.          SPACE
  1483. GLEOFRET CLI   EOFCHAR,C':'        Stopped at a colon?
  1484.          BNE   GLBADCHR            No, give error message
  1485.          LA    R15,12              Else return normal eof
  1486.          LM    R0,R14,GLSAVE
  1487.          BR    R14
  1488.          SPACE
  1489. GLBADCHR DMSERR LET=E,NUM=5,TEXT='Invalid character ''..'' in ''.......X
  1490.                .............'' at line .......... position ...',       X
  1491.                RENT=NO,SUB=(CHARA,(EOFCHAR,1),CHAR8A,IFN,DECA,RDITEM,DEX
  1492.                CA,EOFPOS)
  1493.          MVI   RTNCODE+3,36        Set RC = 36
  1494.          B     CMSRTN              Direct return to CMS
  1495.          SPACE
  1496. GLSAVE   DS    8D                  Local save area
  1497. HQXTRT   TRT   0(*-*,R3),0(R5)     TRT to check valid characters
  1498. GLTR     TR    0(*-*,R2),0(R3)     Translate to ASCII or binary
  1499.          EJECT
  1500. *
  1501. * WR128 - Write 128 bytes of data to a MacBinary output file.
  1502. *         At entry, R1 -> 128 bytes to be written.
  1503. *
  1504. WR128    DS    0H
  1505.          STM   R0,R15,WRSAVE       Save registers
  1506.          L     R2,WRITEM           Increment line number
  1507.          LA    R2,1(R2)
  1508.          ST    R2,WRITEM
  1509.          OI    FLAGS,WROPEN        Remember output file is open
  1510.          ST    R1,WRADDR           Store buffer address
  1511.          LA    R1,OUTPLIST         R1 -> PLIST
  1512.          L     R15,AWRBUF          R15 -> WRBUF entry
  1513.          BALR  R14,R15             Call WRBUF
  1514.          BZ    WRRET               If ok, ready to return
  1515.          LR    R2,R15              Copy error code to R2
  1516.          DMSERR LET=S,NUM=105,                                         X
  1517.                TEXT='Error ''..'' writing file ''....................''X
  1518.                 on disk',SUB=(DEC,(R2),CHAR8A,OFN),RENT=NO
  1519.          LA    R2,100(R2)          Set RC = 1nn
  1520.          ST    R2,RTNCODE
  1521.          B     CMSRTN              Direct return to CMS
  1522.          SPACE
  1523. WRRET    LM    R0,R15,WRSAVE       Restore registers
  1524.          BR    R14                 Return to caller
  1525.          SPACE
  1526. WRSAVE   DS    8D                  Local save area
  1527.          EJECT
  1528. *
  1529. * CRCCALC - Update CRCVAL for a string.  At entry, R0 = string length
  1530. *           and R1 -> string.
  1531. *
  1532. CRCCALC  DS    0H
  1533.          STM   R0,R15,CRCSAVE      Save registers
  1534.          LTR   R7,R0               R7 = BCT count
  1535.          BZ    CRCRTN              If zero, just return
  1536.          LR    R6,R1               R6 -> first byte
  1537.          SR    R3,R3               R3 = current CRC
  1538.          ICM   R3,B'1100',CRCVAL     (in msb)
  1539.          L     R4,=V(XMDMTAB)      R4 -> CRC table
  1540.          SR    R5,R5               R5 = 0 for table entries
  1541. CRCLOOP  EQU   *                   Loop for each character
  1542.          SR    R2,R2                    Shift CRC and get old
  1543.          SLDL  R2,8                       msb in R2
  1544.          ICM   R3,B'0100',0(R6)         Append new byte to CRC
  1545.          SLL   R2,1                     R2 = table offset
  1546.          LA    R2,0(R2,R4)              R2 -> table entry
  1547.          ICM   R5,B'1100',0(R2)         R5 = table entry
  1548.          XR    R3,R5                    update CRC
  1549.          LA    R6,1(R6)                 R6 -> next byte
  1550.          BCT   R7,CRCLOOP               Repeat to end of string
  1551.          STCM  R3,B'1100',CRCVAL   Store final CRC
  1552. CRCRTN   LM    R0,R15,CRCSAVE      Restore registers
  1553.          BR    R14                 Return to caller
  1554.          SPACE
  1555. CRCSAVE  DS    8D                  Local save area
  1556.          EJECT
  1557. *
  1558. * Error message code
  1559. *
  1560.          SPACE
  1561. STATERR  ST    R15,RTNCODE         Save return code from STATE
  1562.          LA    R2,8(R1)            R2 -> filename in PLIST
  1563.          C     R15,=F'28'          Return if STATE typed message
  1564.          BL    CMSRTN
  1565.          BE    STNOFIL             RC = 28 is file not found
  1566. *                                  Else disk not accessed (RC = 36)
  1567.          LA    R2,16(R2)           R2 -> filemode in plist
  1568.          DMSERR NUM=69,LET=E,TEXT='Disk ''..'' not accessed',          X
  1569.                SUB=(CHARA,((R2),1))
  1570.          B     CMSRTN
  1571.          SPACE
  1572. STNOFIL  DMSERR NUM=2,LET=E,                                           X
  1573.                TEXT='File ''....................'' not found',         X
  1574.                SUB=(CHAR8A,(R2))
  1575.          B     CMSRTN
  1576.          SPACE
  1577. LRECLERR MVI   RTNCODE+3,32        Set RC = 32
  1578.          DMSERR NUM=44,LET=E,TEXT='Record length exceeds allowable maxiX
  1579.                mum'
  1580.          B     CMSRTN
  1581.          SPACE
  1582. EXIERR   LTR   R15,R15             If non-zero RC, handle STATE error
  1583.          BNZ   STATERR
  1584.          LA    R2,8(R1)            R2 -> filemame in plist
  1585.          DMSERR NUM=24,LET=E,                                          X
  1586.                TEXT='File ''....................'' already exists',    X
  1587.                SUB=(CHAR8A,(R2))
  1588.          MVI   RTNCODE+3,28
  1589.          B     CMSRTN
  1590.          SPACE
  1591. ROERR    EQU   *
  1592.          USING ADTSECT,R2
  1593.          LA    R2,ADTM             Point to mode letter
  1594.          DROP  R2
  1595.          DMSERR NUM=37,LET=E,TEXT='Disk ''..'' is read-only',          X
  1596.                SUB=(CHARA,((R2),1))
  1597.          MVI   RTNCODE+3,36
  1598.          B     CMSRTN
  1599.          SPACE
  1600. CMSRTN   EQU   *                   Return to CMS
  1601.          TM    FLAGS,RDOPEN        Is input file open?
  1602.          BZ    RTN0                No, skip finis
  1603.          L     R15,AFINIS
  1604.          LA    R1,INPLIST
  1605.          BALR  R14,R15             Close input file
  1606. RTN0     TM    FLAGS,WROPEN        Is output file open?
  1607.          BZ    RTN1                No, skip finis
  1608.          L     R15,AFINIS
  1609.          LA    R1,OUTPLIST
  1610.          BALR  R14,R15             Close output file
  1611. RTN1     DMSKEY RESET              Restore user key
  1612.          SSM   =X'FF'              Allow interrupts
  1613.          L     R15,RTNCODE         R15 = return code
  1614.          LM    R0,R14,REGSAVE      Restore other registers
  1615.          BR    R14                 Return to caller
  1616.          EJECT
  1617. *
  1618. * GETID - Invoke IDENTIFY to get local node id.  Set the
  1619. *         node id to blanks if any error.
  1620. *
  1621.          SPACE
  1622. GETID    DS    0H
  1623.          STM   R14,R1,GETSAVE      Save registers
  1624.          MVC   NODEID(8),=CL8' '   Initialize node id to blanks
  1625.          LA    R1,IDPLIST          Execute IDENTIFY
  1626.          SVC   202
  1627.          DC    AL4(1)
  1628.          LTR   R15,R15             Just return if any errors
  1629.          BNZ   GETIDRTN
  1630.          RDTERM RDRESP             Get response
  1631.          C     R0,=F'19'           At least 19 bytes?
  1632.          BL    GETIDRTN            No, just return
  1633.          MVC   NODEID(8),RDRESP+12  Copy node id from IDENTIFY
  1634. GETIDRTN LM    R14,R1,GETSAVE      Restore registers
  1635.          BR    R14                 Return
  1636.          SPACE
  1637. GETSAVE  DS    2D                  Save area: R14, R15, R0, R1
  1638. IDPLIST  DS    0D
  1639.          DC    CL8'IDENTIFY'       IDENTIFY command
  1640.          DC    CL8'('
  1641.          DC    CL8'LIFO'
  1642.          DC    8X'FF'
  1643. RDRESP   DS    CL130               RDTERM buffer
  1644.          EJECT
  1645. *
  1646. * DECCVT -- Convert decimal number in plist to binary
  1647. *
  1648. * Entry: R1 -> 8-byte number, R14 = return address
  1649. * Exit: R2 = -1 if conversion error, or contains binary number;
  1650. *       condition code set from R2
  1651. *
  1652. DECCVT   DS    0H
  1653.          STM   R3,R1,DECSAVE       Save registers
  1654.          SR    R2,R2               Result = 0
  1655.          LA    R3,8                Examine 8 bytes
  1656.          SR    R4,R4               R4 = 0 for IC
  1657. *                                  R1 -> first byte of token
  1658. DECLOOP  EQU   *                   Scan number and accumulate result
  1659.          CLI   0(R1),C' '               Exit when blank encountered
  1660.          BE    DECEND
  1661.          CLI   0(R1),C'0'               Check for a valid digit
  1662.          BL    DECERR
  1663.          CLI   0(R1),C'9'
  1664.          BH    DECERR
  1665.          IC    R4,0(R1)                 Get binary digit in R4
  1666.          SH    R4,=H'240'
  1667.          MH    R2,=H'10'                Result = 10*result + digit
  1668.          AR    R2,R4
  1669.          LA    R1,1(R1)                 R1 -> next digit
  1670.          BCT   R3,DECLOOP               Repeat
  1671.          B     DECEND              Skip error result
  1672. DECERR   LH    R2,=H'-1'           Error: return -1
  1673. DECEND   LM    R3,R1,DECSAVE       Restore all registers except R2
  1674.          LTR   R2,R2               Set condition code for caller
  1675.          BR    R14                 Return to caller
  1676.          SPACE
  1677. DECSAVE  DS    8D                  Save area R3...R15, R0, R1
  1678.          EJECT
  1679. *
  1680. * NUMTOSTR - Store character form of a number in a buffer.
  1681. *            At entry, R0 contains the number and R1 points to
  1682. *            the buffer.  Returns the length of the string
  1683. *            stored in R0.
  1684. *
  1685. NUMTOSTR DS    0H
  1686.          STM   R0,R15,NUMSAVE      Save registers
  1687.          CVD   R0,NUMBUF           Convert number to decimal
  1688.          TM    FLAGS2,EXECVAR+NOCOMMA Check if commas not wanted
  1689.          BNZ   ALTEDIT
  1690.          MVC   EDITBUFF(15),EDITPAT  Copy pattern for EDMK
  1691.          LA    R1,EDITBUFF+14      R1 -> last byte
  1692.          EDMK  EDITBUFF(15),NUMBUF+2 Convert to characters
  1693.          LA    R2,EDITBUFF+15      R2 -> past last byte
  1694.          B     NUMEND
  1695.          SPACE
  1696. ALTEDIT  MVC   EDITBUFF(12),EDITPAT2  Copy pattern for EDMK
  1697.          LA    R1,EDITBUFF+11      R1 -> last byte
  1698.          EDMK  EDITBUFF(12),NUMBUF+2 Convert to characters
  1699.          LA    R2,EDITBUFF+12      R2 -> past last byte
  1700. NUMEND   SR    R2,R1               Get length in R2
  1701.          ST    R2,NUMSAVE          Store to return in R0
  1702.          BCTR  R2,0                Decrement for EX
  1703.          L     R3,NUMSAVE+4        R3 -> buffer
  1704.          EX    R2,NUMMVC           Copy number to buffer
  1705.          LM    R0,R15,NUMSAVE      Return to caller
  1706.          BR    R14
  1707.          SPACE
  1708. NUMSAVE  DS    8D                  Local save area
  1709. NUMBUF   DS    1D                  Buffer for CVD
  1710. NUMMVC   MVC   0(*-*,R3),0(R1)     Copy number to buffer
  1711. EDITPAT  DC    X'4020206B2020206B2020206B202120'  EDIT pattern
  1712. EDITPAT2 DC    X'402020202020202020202120' alternate pattern
  1713. EDITBUFF DS    15C                 Buffer for EDIT result
  1714.          EJECT
  1715. *
  1716. * SEC2DATE - Store the character form of a Macintosh date in a
  1717. *            buffer.  At entry, R0 contains the number of seconds
  1718. *            since midnight, Jan. 1, 1904.  R1 points to the buffer
  1719. *            which will contains the date.  The length of the date
  1720. *            is returned in R0.
  1721. *
  1722. SEC2DATE DS    0H
  1723.          STM   R0,R15,SECSAVE      Save registers
  1724.          OI    FLAGS2,NOCOMMA      Suppress commas for NUMTOSTR
  1725. * Get elapsed days, hours, minutes, seconds
  1726.          LR    R1,R0               R0, R1 = total seconds
  1727.          SR    R0,R0
  1728.          D     R0,=F'86400'        Divide to get days
  1729.          ST    R1,SECDAYS          Store elapsed days
  1730.          LR    R1,R0               R0, R1 = remaining seconds
  1731.          SR    R0,R0
  1732.          D     R0,=F'3600'         Divide to get hours
  1733.          ST    R1,SECHRS           Store elapsed hours
  1734.          LR    R1,R0               R0, R1 = remaining seconds
  1735.          SR    R0,R0
  1736.          D     R0,=F'60'           Divide to get mins, seconds
  1737.          ST    R1,SECMIN           Store elpased minutes
  1738.          ST    R0,SECSEC           Store elpased seconds
  1739. * Calculate day of the week
  1740.          SR    R0,R0               Divide days by 7
  1741.          L     R1,SECDAYS
  1742.          D     R0,=F'7'
  1743.          ST    R0,SECWKDAY         Store remainder
  1744. * Calculate month, day and year from elapsed days
  1745.          L     R3,SECDAYS          R3 = elapsed days
  1746.          A     R3,=F'1401'         Add constant to get days from
  1747. *                                    March 1, 1900
  1748. *                                  Get 4*Jdate + 3
  1749.          SLL   R3,2
  1750.          LA    R3,3(R3)
  1751.          SR    R2,R2               Divide by 1461
  1752.          D     R2,=F'1461'
  1753. *                                  R2 = day, R3 = year
  1754.          SRL   R2,2                Day = day/4 + 1
  1755.          LA    R2,1(R2)
  1756.          MH    R2,=H'5'            Get (5*day-3)/153
  1757.          S     R2,=F'3'
  1758.          SR    R4,R4
  1759.          LR    R5,R2
  1760.          D     R4,=F'153'
  1761. *                                  R4 = day, R5 = month
  1762.          LR    R2,R5               R2 = month
  1763.          SR    R0,R0               Day = day/5 + 1
  1764.          LR    R1,R4
  1765.          D     R0,=F'5'
  1766.          LA    R1,1(R1)            R1 = day, R2 = month, R3 = year
  1767.          LA    R2,3(R2)            Month = Month + 3
  1768.          C     R2,=F'12'           If > 12, subtract 12
  1769.          BNH   KEEPMON
  1770.          S     R2,=F'12'
  1771.          LA    R3,1(R3)            And add 1 to year
  1772. KEEPMON  EQU   *
  1773.          ST    R1,SECDAY           Store day of month
  1774.          ST    R2,SECMONTH         Store month
  1775.          LA    R3,1900(R3)         Add base year to year
  1776.          ST    R3,SECYEAR
  1777. * Format results in character string form
  1778.          SR    R2,R2               R2 = string length
  1779.          L     R3,SECSAVE+4        R3 -> next available byte
  1780.          L     R1,SECWKDAY         R1 = weekday (0 - 6)
  1781.          MH    R1,=H'3'            Convert to table offset
  1782.          LA    R1,DAYLIST(R1)      R1 -> weekday
  1783.          MVC   0(3,R3),0(R1)       Copy weekday
  1784.          MVC   3(2,R3),=C', '      Append separator
  1785.          L     R1,SECMONTH         R1 = month (1 - 12)
  1786.          BCTR  R1,0                Convert to table offset
  1787.          MH    R1,=H'3'
  1788.          LA    R1,MONLIST(R1)      R1 -> month
  1789.          MVC   5(3,R3),0(R1)       Copy month
  1790.          MVI   8(R3),C' '          Append separator
  1791.          LA    R2,9(R2)            Increment length
  1792.          LA    R3,9(R3)            Increment pointer
  1793.          L     R0,SECDAY           R0 = day of the month
  1794.          LR    R1,R3               R1 -> buffer
  1795.          BAL   R14,NUMTOSTR        Store string in buffer
  1796.          AR    R2,R0               Increment length
  1797.          AR    R3,R0               Increment pointer
  1798.          MVC   0(2,R3),=C', '      Append separator
  1799.          LA    R2,2(R2)            Increment length
  1800.          LA    R3,2(R3)            Increment pointer
  1801.          L     R0,SECYEAR          R0 = year
  1802.          LR    R1,R3               R1 -> buffer
  1803.          BAL   R14,NUMTOSTR        Store string in buffer
  1804.          AR    R2,R0               Increment length
  1805.          AR    R3,R0               Increment pointer
  1806.          MVC   0(2,R3),=C'  '      Append separator
  1807.          LA    R2,2(R2)            Increment length
  1808.          LA    R3,2(R3)            Increment pointer
  1809.          L     R0,SECHRS           R0 = hours (0 - 23)
  1810.          C     R0,=F'12'           Morning if < 12
  1811.          BL    SECAM
  1812. *                                  Else afternoon
  1813.          MVC   AMPM(2),=C'PM'      Store "PM"
  1814.          C     R0,=F'12'           If hours = 12, keep
  1815.          BE    PMKEEP
  1816.          S     R0,=F'12'           Else subtract 12
  1817. PMKEEP   B     USEHRS              Ready to format hours
  1818.          SPACE
  1819. SECAM    MVC   AMPM(2),=C'AM'      Store "AM"
  1820.          LTR   R0,R0               Use hours if > 0
  1821.          BNZ   USEHRS
  1822.          LA    R0,12               Else set hours to 12
  1823. USEHRS   LR    R1,R3               R1 -> buffer
  1824.          BAL   R14,NUMTOSTR        Store string in buffer
  1825.          AR    R2,R0               Increment length
  1826.          AR    R3,R0               Increment pointer
  1827.          L     R0,SECMIN           R0 = minutes
  1828.          AH    R0,=H'100'          Add 100 to use 3 columns
  1829.          LR    R1,R3               R1 -> buffer
  1830.          BAL   R14,NUMTOSTR        Store string in buffer
  1831.          MVI   0(R3),C':'          Replace "1" by ":"
  1832.          AR    R2,R0               Increment length
  1833.          AR    R3,R0               Increment pointer
  1834.          L     R0,SECSEC           R0 = seconds
  1835.          AH    R0,=H'100'          Add 100 to use 3 columns
  1836.          LR    R1,R3               R1 -> buffer
  1837.          BAL   R14,NUMTOSTR        Store string in buffer
  1838.          MVI   0(R3),C':'          Replace "1" by ":"
  1839.          AR    R2,R0               Increment length
  1840.          AR    R3,R0               Increment pointer
  1841.          MVI   0(R3),C' '          Append separator
  1842.          MVC   1(2,R3),AMPM        Append AM or PM
  1843.          LA    R2,3(R2)            R2 = final length
  1844.          ST    R2,SECSAVE          Store to return in R0
  1845.          NI    FLAGS2,255-NOCOMMA  Reset comma suppression
  1846.          LM    R0,R15,SECSAVE      Restore registers
  1847.          BR    R14                 Return to caller
  1848.          SPACE
  1849. SECSAVE  DS    8D                  Local save area
  1850. SECDAYS  DS    1F                  Elapsed days
  1851. SECHRS   DS    1F                  Elapsed hours
  1852. SECMIN   DS    1F                  Elapsed minutes
  1853. SECSEC   DS    1F                  Elapsed seconds
  1854. SECWKDAY DS    1F                  Weekday (0 = Fri, 1 = Sat ...)
  1855. SECDAY   DS    1F                  Day of the month
  1856. SECMONTH DS    1F                  Month
  1857. SECYEAR  DS    1F                  Year
  1858. DAYLIST  DC    C'FriSatSunMonTueWedThu'
  1859. MONLIST  DC    C'JanFebMarAprMayJunJulAugSepOctNovDec'
  1860. AMPM     DS    2C
  1861.          EJECT
  1862. *
  1863. * TYPEHDR - Type description of header information
  1864. *
  1865. TYPEHDR  DS    0H
  1866.          STM   R0,R15,TYPHDSAV     Save registers
  1867.          L     R8,=A(DATABUFF)     R8 -> message buffer
  1868.          LINEDIT TEXT='File: ''....................''',RENT=NO,        X
  1869.                SUB=(CHAR8A,IFN),DOT=NO,BUFFA=(R8),DISP=NONE
  1870.          SR    R2,R2               R2 = message length
  1871.          IC    R2,0(R8)
  1872.          LA    R3,1(R2,R8)         R3 -> next byte
  1873.          MVC   0(10,R3),=C'  Format: '  Append format info.
  1874.          TM    FLAGS,MACBIN        Check for MacBinary
  1875.          BO    FMTBIN
  1876.          MVC   10(6,R3),=C'BinHex' Else BinHex format
  1877.          LA    R2,16(R2)           Get new length
  1878.          B     TYPEFMT             Ready to type line
  1879.          SPACE
  1880. FMTBIN   MVC   10(9,R3),=C'MacBinary'  MacBinary format
  1881.          LA    R2,19(R2)           Get new length
  1882. TYPEFMT  STC   R2,0(R8)            Store new length
  1883.          BAL   R14,TYPEDESC        Type or stack line
  1884.          MVC   1(11,R8),=C'Filename: ''' Generate filename msg.
  1885.          MVC   12(63,R8),HDFN      append filename
  1886.          L     R2,FRASCADR         translate to EBCDIC
  1887.          TR    12(63,R8),0(R2)
  1888.          SR    R1,R1               Get length of filename
  1889.          IC    R1,HDFNLEN
  1890.          LA    R1,12(R1)           Add length of message
  1891.          STC   R1,0(R8)            Store length for TYPEDESC
  1892.          LA    R1,0(R1,R8)         R1 -> past filename
  1893.          MVI   0(R1),C''''         Append apostrophe
  1894.          BAL   R14,TYPEDESC        Type or stack line
  1895.          MVC   1(7,R8),=C'Type: '''  Generate type,
  1896.          MVC   8(4,R8),HDFTYP      creator message
  1897.          TR    8(4,R8),0(R2)       Translate to EBCDIC
  1898.          MVC   12(13,R8),=C'''  Creator: '''
  1899.          MVC   25(4,R8),HDFCREAT
  1900.          TR    25(4,R8),0(R2)      Translate to EBCDIC
  1901.          MVC   29(10,R8),=C'''  Flags: '
  1902.          ICM   R3,B'1100',HDFLAGS  Get flags in msb of R3
  1903.          LA    R4,FLAGTEXT         R4 -> list of names
  1904.          LA    R5,16               R5 = bit count
  1905.          LA    R6,39               R6 = buffer offset
  1906. FLGLOOP  EQU   *                   Loop to set flag names
  1907.          SR    R2,R2                    Get next bit in R2
  1908.          SLDL  R2,1
  1909.          LTR   R2,R2                    Is bit set?
  1910.          BZ    FLGNEXT                  No, skip name
  1911.          C     R6,=F'39'                First name?
  1912.          BE    SKIPPLUS                 Yes, skip "+"
  1913.          IC    R7,=C'+'                 Else append "+"
  1914.          STC   R7,0(R6,R8)
  1915.          LA    R6,1(R6)
  1916. SKIPPLUS LA    R7,0(R6,R8)              R7 -> where to put text
  1917.          MVC   0(4,R7),0(R4)            Copy flag name
  1918.          LA    R6,4(R6)
  1919. FLGNEXT  LA    R4,4(R4)                 R4 -> next name
  1920.          BCT   R5,FLGLOOP
  1921.          C     R6,=F'39'           Any flags?
  1922.          BNE   HAVEFLGS            Yes, continue
  1923.          LA    R7,0(R6,R8)         Else append "none"
  1924.          MVC   0(4,R7),=C'none'
  1925.          LA    R6,4(R6)
  1926. HAVEFLGS BCTR  R6,0                R6 = line length
  1927.          STC   R6,0(R8)            Store for TYPEDESC
  1928.          BAL   R14,TYPEDESC        Type or stack line
  1929.          ICM   R3,B'1111',HDDATALN Get data fork length
  1930.          ICM   R4,B'1111',HDRSCLN  Get resource fork length
  1931.          MVC   1(16,R8),=C'Data fork size: '  Copy start of size
  1932.          LA    R5,16               R5 = message length
  1933.          LA    R6,1(R5,R8)         R6 -> next byte
  1934.          LR    R0,R3               R0 = data size
  1935.          LR    R1,R6               R1 -> buffer
  1936.          BAL   R14,NUMTOSTR        Store number in string form
  1937.          AR    R5,R0               Update length and address
  1938.          AR    R6,R0
  1939.          MVC   0(22,R6),=C'; Resource fork size: '  Copy rest
  1940.          LA    R5,22(R5)           Update length and address
  1941.          LA    R6,22(R6)
  1942.          LR    R0,R4               R0 = resource size
  1943.          LR    R1,R6               R1 -> buffer
  1944.          BAL   R14,NUMTOSTR        Store number in string form
  1945.          AR    R5,R0               Update length
  1946.          STC   R5,0(R8)            Store length for TYPEDESC
  1947.          BAL   R14,TYPEDESC        Type or stack line
  1948.          TM    FLAGS,MACBIN        MacBinary file?
  1949.          BZ    TYPHEND             No, all info. typed
  1950.          MVC   1(15,R8),=C'      Created: '  Start of creation date
  1951.          LA    R5,15               R5 = message length
  1952.          LA    R1,1(R5,R8)         R1 -> next byte
  1953.          ICM   R0,B'1111',HDCRDATE R0 = creation date
  1954.          BAL   R14,SEC2DATE        Store date in character form
  1955.          AR    R5,R0               Update length
  1956.          STC   R5,0(R8)            Store length for TYPEDESC
  1957.          BAL   R14,TYPEDESC        Type or stack line
  1958.          MVC   1(15,R8),=C'Last Modified: '  Start of last mod date
  1959.          LA    R5,15               R5 = message length
  1960.          LA    R1,1(R5,R8)         R1 -> next byte
  1961.          ICM   R0,B'1111',HDMDDATE R0 = creation date
  1962.          BAL   R14,SEC2DATE        Store date in character form
  1963.          AR    R5,R0               Update length
  1964.          STC   R5,0(R8)            Store length for TYPEDESC
  1965.          BAL   R14,TYPEDESC        Type or stack line
  1966. TYPHEND  LA    R1,=CL8'CONWAIT'    Call CONWAIT to wait for
  1967.          SVC   202                   output to finish
  1968.          DC    AL4(1)              (following code can take a while)
  1969.          LM    R0,R15,TYPHDSAV     Restore registers
  1970.          BR    R14                 Return to caller
  1971.          SPACE
  1972. TYPHDSAV DS    8D                  Local save area
  1973.          EJECT
  1974. *
  1975. * TYPEDESC - Type a description line or stack the line (depending
  1976. *            on the options the user has specified).  The first byte
  1977. *            of DATABUFF contains the line length, and is followed
  1978. *            by the text.
  1979. *
  1980. TYPEDESC DS    0H
  1981.          STM   R0,R15,TYPSAVE      Save registers
  1982.          L     R2,=A(DATABUFF)     R2 -> string length byte
  1983.          SR    R1,R1               Get length in R1
  1984.          IC    R1,0(R2)
  1985.          TM    FLAGS,STKDESC       Stacking requested?
  1986.          BO    DOSTACK             Yes, go do it
  1987.          STH   R1,TYPLEN           Store length for typing
  1988.          LA    R1,TYPLIST          R1 -> TYPLIN plist
  1989.          SVC   202                 Type the line
  1990.          DC    AL4(1)              Ignore errors
  1991.          B     TYPRTN              Return
  1992.          SPACE
  1993. DOSTACK  MVI   STKORDR,C'F'        Set FIFO default order
  1994.          TM    FLAGS,STKLIFO       LIFO wanted?
  1995.          BZ    KEEPFIFO            No, keep FIFO
  1996.          MVI   STKORDR,C'L'        Else change FIFO to LIFO
  1997. KEEPFIFO STC   R1,STKLEN           Store length for stacking
  1998.          LA    R1,STKLIST          R1 -> ATTN plist
  1999.          SVC   202                 Stack the line
  2000.          DC    AL4(1)              Ignore errors
  2001. TYPRTN   LM    R0,R15,TYPSAVE      Restore registers
  2002.          BR    R14                 Return to caller
  2003.          SPACE
  2004. TYPSAVE  DS    8D                  Local save area
  2005.          EJECT
  2006. *
  2007. * VARHDR - Return header information in REXX variables.  VARHDR
  2008. *          is called instead of TYPEHDR when the STEM option has
  2009. *          been specified.
  2010. *
  2011. VARHDR   DS    0H
  2012.          STM   R0,R15,VARSAVE      Save registers
  2013.          L     R8,=A(DATABUFF)     R8 -> buffer for values
  2014.          L     R1,=A(VARTAB)       R1 -> FN string data
  2015.          MVI   0(R8),8             Store filename length
  2016.          MVC   1(8,R8),IFN         Copy filename
  2017.          BAL   R14,SETVAR          Define stem.FN
  2018.          LA    R1,4(R1)            R1 -> FT string data
  2019.          MVI   0(R8),8             Store filetype length
  2020.          MVC   1(8,R8),IFT         Copy filetype
  2021.          BAL   R14,SETVAR          Define stem.FT
  2022.          LA    R1,4(R1)            R1 -> FM string data
  2023.          MVI   0(R8),2             Store filemode length
  2024.          MVC   1(2,R8),IFM         Copy filemode
  2025.          BAL   R14,SETVAR          Define stem.FM
  2026.          LA    R1,4(R1)            R1 -> FORMAT string data
  2027.          MVI   0(R8),6             Set to BinHex
  2028.          MVC   1(6,R8),=C'BinHex'
  2029.          TM    FLAGS,MACBIN        MacBinary?
  2030.          BZ    USEFMT              No, keep format
  2031.          MVI   0(R8),9             Set to MacBinary
  2032.          MVC   1(9,R8),=C'MacBinary'
  2033. USEFMT   BAL   R14,SETVAR          Define stem.FORMAT
  2034.          LA    R1,4(R1)            R1 -> NAME string data
  2035.          MVC   0(1,R8),HDFNLEN     Copy length of name
  2036.          MVC   1(63,R8),HDFN       Copy maximum text
  2037.          L     R2,FRASCADR         Translate to EBCDIC
  2038.          TR    1(63,R8),0(R2)
  2039.          BAL   R14,SETVAR          Define stem.NAME
  2040.          LA    R1,4(R1)            R1 -> TYPE string data
  2041.          MVI   0(R8),4             Length = 4
  2042.          MVC   1(4,R8),HDFTYP      Copy type text
  2043.          TR    1(4,R8),0(R2)       Translate to EBCDIC
  2044.          BAL   R14,SETVAR          Define stem.TYPE
  2045.          LA    R1,4(R1)            R1 -> CREATOR string data
  2046.          MVI   0(R8),4             Length = 4
  2047.          MVC   1(4,R8),HDFCREAT    Copy type text
  2048.          TR    1(4,R8),0(R2)       Translate to EBCDIC
  2049.          BAL   R14,SETVAR          Define stem.CREATOR
  2050.          LA    R1,4(R1)            R1 -> FLAGS string data
  2051.          ICM   R3,B'1100',HDFLAGS  Get flags in msb of R3
  2052.          LA    R4,FLAGTEXT         R4 -> list of names
  2053.          LA    R5,16               R5 = bit count
  2054.          LA    R6,1                R6 = buffer offset
  2055. FLGLP2   EQU   *                   Loop to set flag names
  2056.          SR    R2,R2                    Get next bit in R2
  2057.          SLDL  R2,1
  2058.          LTR   R2,R2                    Is bit set?
  2059.          BZ    FLGNXT2                  No, skip name
  2060.          C     R6,=F'1'                 First name?
  2061.          BE    SKIPPL2                  Yes, skip "+"
  2062.          IC    R7,=C'+'                 Else append "+"
  2063.          STC   R7,0(R6,R8)
  2064.          LA    R6,1(R6)
  2065. SKIPPL2  LA    R7,0(R6,R8)              R7 -> where to put text
  2066.          MVC   0(4,R7),0(R4)            Copy flag name
  2067.          LA    R6,4(R6)
  2068. FLGNXT2  LA    R4,4(R4)                 R4 -> next name
  2069.          BCT   R5,FLGLP2
  2070.          C     R6,=F'1'            Any flags?
  2071.          BNE   HAVEFLG2            Yes, continue
  2072.          LA    R7,0(R6,R8)         Else append "none"
  2073.          MVC   0(4,R7),=C'none'
  2074.          LA    R6,4(R6)
  2075. HAVEFLG2 BCTR  R6,0                R6 = line length
  2076.          STC   R6,0(R8)            Store for SETVAR
  2077.          BAL   R14,SETVAR          Define stem.FLAGS
  2078.          LA    R1,4(R1)            R1 -> DATASIZE string data
  2079.          LR    R2,R1               Save R1 across NUMTOSTR
  2080.          ICM   R0,B'1111',HDDATALN  R0 = size of data fork
  2081.          LA    R1,1(R8)            R1 -> buffer for number
  2082.          BAL   R14,NUMTOSTR        Convert to string
  2083.          STC   R0,0(R8)            Store string length
  2084.          LR    R1,R2               Restore R1 for SETVAR
  2085.          BAL   R14,SETVAR          Define stem.DATASIZE
  2086.          LA    R1,4(R1)            R1 -> RESCSIZE string data
  2087.          LR    R2,R1               Save R1 across NUMTOSTR
  2088.          ICM   R0,B'1111',HDRSCLN  R0 = size of resource fork
  2089.          LA    R1,1(R8)            R1 -> buffer for number
  2090.          BAL   R14,NUMTOSTR        Convert to string
  2091.          STC   R0,0(R8)            Store string length
  2092.          LR    R1,R2               Restore R1 for SETVAR
  2093.          BAL   R14,SETVAR          Define stem.RESCSIZE
  2094.          TM    FLAGS,MACBIN        MacBinary file?
  2095.          BZ    VARRTN              No, all info. defined
  2096.          LA    R1,4(R1)            R1 -> CRDATE string data
  2097.          LR    R2,R1               Save R1 across SEC2DATE
  2098.          ICM   R0,B'1111',HDCRDATE R0 = creation date
  2099.          LA    R1,1(R8)            R1 -> buffer for number
  2100.          BAL   R14,SEC2DATE        Convert to string
  2101.          STC   R0,0(R8)            Store string length
  2102.          LR    R1,R2               Restore R1 for SETVAR
  2103.          BAL   R14,SETVAR          Define stem.CRDATE
  2104.          LA    R1,4(R1)            R1 -> MDDATE string data
  2105.          LR    R2,R1               Save R1 across SEC2DATE
  2106.          ICM   R0,B'1111',HDMDDATE R0 = last modified date
  2107.          LA    R1,1(R8)            R1 -> buffer for number
  2108.          BAL   R14,SEC2DATE        Convert to string
  2109.          STC   R0,0(R8)            Store string length
  2110.          LR    R1,R2               Restore R1 for SETVAR
  2111.          BAL   R14,SETVAR          Define stem.MDDATE
  2112. VARRTN   LM    R0,R15,VARSAVE      Restore registers
  2113.          BR    R14                 Return to caller
  2114.          SPACE
  2115. VARSAVE  DS    8D                  Local save area
  2116.          EJECT
  2117. *
  2118. * SETVAR - Define REXX variable to a given value.  The variable
  2119. *          to be defined will be stemname.suffix, where "stemname"
  2120. *          was specified in the "STEM" option, and R1 contains the
  2121. *          address of a pointer to the length and text of "suffix".
  2122. *          The length and text of the variable's value is found in
  2123. *          DATABUFF.
  2124. *
  2125. SETVAR   DS    0H
  2126.          STM   R0,R15,SETSAVE      Save registers
  2127.          MVC   NAMEBUFF(8),STEMNAME  Copy stem name
  2128.          L     R3,STEMSIZE         R3 = length of name
  2129.          LA    R2,NAMEBUFF(R3)     R2 -> next available byte
  2130.          MVI   0(R2),C'.'          Append period
  2131.          LA    R2,1(R2)            Increment pointer
  2132.          LA    R3,1(R3)            Increment size
  2133.          L     R1,0(R1)            R1 -> length, text for suffix
  2134.          SR    R5,R5               R5 = length
  2135.          IC    R5,0(R1)
  2136.          LA    R4,1(R1)            R4 -> text
  2137.          BCTR  R5,0                Decrement length for EX
  2138.          EX    R5,NAMEMVC
  2139.          LA    R3,1(R3,R5)         R3 = length of variable name
  2140.          LA    R2,NAMEBUFF         R2 -> value of name
  2141.          L     R1,=A(DATABUFF)     R1 -> length, text of value
  2142.          SR    R5,R5               R5 = length of value
  2143.          IC    R5,0(R1)
  2144.          LA    R4,1(R1)            R4 -> value for variable
  2145.          LA    R6,MYSHBLK          Address shared variable block
  2146.          USING SHVBLOCK,R6
  2147.          XC    SHVBLOCK(SHVBLEN),SHVBLOCK  Initialize to zeros
  2148.          MVI   SHVCODE,C'S'        Store code to set a variable
  2149.          STM   R2,R5,SHVNAMA       Store name and value info.
  2150.          XC    EXTPLIST(16),EXTPLIST  Initialize extended plist
  2151.          DROP  R6                  Done with shared variable block
  2152.          LA    R1,=CL8'EXECCOMM'   R1 -> function name
  2153.          ST    R1,EXTPLIST         Store in extended plist
  2154.          ICM   R1,B'1000',=X'02'   Indicate subcommand call
  2155.          ST    R6,EXTPLIST+12      Store A(shared variable block)
  2156.          LA    R0,EXTPLIST         R0 -> extended plist
  2157.          SVC   202                 Invoke EXECCOMM to set variable
  2158.          DC    AL4(1)              Ignore errors
  2159.          LTR   R15,R15             Check return code
  2160.          BZ    SETRTN              Ok if zero
  2161.          C     R15,=F'-3'          Check for environment error
  2162.          BE    BADENV
  2163.          LR    R2,R15              Save RC
  2164.          DMSERR NUM=632,LET=E,                                         X
  2165.                TEXT='Error setting EXEC variable: RC=..... from ''EXECCX
  2166.                OMM'' function',SUB=(DEC,(R2))
  2167.          MVI   RTNCODE+3,200       Set RC = 200
  2168.          B     CMSRTN              Return to CMS
  2169.          SPACE
  2170. BADENV   DMSERR NUM=631,LET=E,                                         X
  2171.                TEXT='''STEM'' option is only available from an EXEC2 orX
  2172.                 REXX exec'
  2173.          MVI   RTNCODE+3,4         Set RC = 4
  2174.          B     CMSRTN              Return to CMS
  2175.          SPACE
  2176. SETRTN   LM    R0,R15,SETSAVE      Restore register
  2177.          BR    R14                 Return to caller
  2178.          SPACE
  2179. SETSAVE  DS    8D                  Local save area
  2180. NAMEBUFF DS    3D                  Variable name constructed here
  2181. MYSHBLK  DS    4D                  Shared variable block
  2182. EXTPLIST DS    4F                  Extended plist for EXECCOMM
  2183. NAMEMVC  MVC   0(*-*,R2),0(R4)     Append suffix after stem
  2184.          EJECT
  2185. *
  2186. * BINHEX Data Area:
  2187. *
  2188.          SPACE
  2189. NODEID   DS    1D                  Local node id
  2190. BROWNID  DC    CL8'BROWNVM'        Brown node id
  2191. INPLIST  DS    0D                  Input file all-purpose plist
  2192. INCMMD   DS    CL8                      command name (ignored for BALR)
  2193. IFN      DS    CL8                      filename
  2194. IFT      DS    CL8                      filetype
  2195. IFM      DS    CL2                      filemode
  2196. RDUN1    DS    H                        unused
  2197. RDADDR   DS    A                        statefst addr.; rdbuf buffer
  2198. RDBUFLTH DS    F                        size of rdbuf buffer
  2199. RDFV     DS    C                        recfm (F or V)
  2200. RDFLAG   DS    X                        plist flag
  2201. RDUN2    DS    H                        unused
  2202. RDLGTH   DS    A                        no. of bytes read (filled-in)
  2203. RDITEM   DS    A                        extended item number
  2204. RDITEC   DS    A                        extended number of items
  2205. RDWP     DS    A                        write pointer
  2206. RDRP     DS    A                        read pointer
  2207.          SPACE
  2208. OUTPLIST DS    0D                  Output file all-purpose plist
  2209. OUTCMMD  DS    CL8                      command name (ignored for BALR)
  2210. OFN      DS    CL8                      filename
  2211. OFT      DS    CL8                      filetype
  2212. OFM      DS    CL2                      filemode
  2213. WRUN1    DS    H                        unused
  2214. WRADDR   DS    A                        statefst addr.; wrbuf buffer
  2215. WRBUFLTH DS    F                        size of wrbuf buffer
  2216. WRFV     DS    C                        recfm (F or V)
  2217. WRFLAG   DS    X                        plist flag
  2218. WRUN2    DS    H                        unused
  2219. WRUN3    DS    A                        unused
  2220. WRITEM   DS    A                        extended item number
  2221. WRITEC   DS    A                        extended number of items
  2222. WRWP     DS    A                        write pointer
  2223. WRRP     DS    A                        read pointer
  2224.          SPACE
  2225.          DS    0D                  TYPLIN Plist to type description
  2226. TYPLIST  DC    CL8'TYPLIN'              command name for SVC 202
  2227.          DC    AL1(1)                   obsolete terminal number
  2228.          DC    AL3(DATABUFF+1)          string address
  2229.          DC    C'B'                     color (Black)
  2230.          DC    AL1(0)                   flag byte
  2231. TYPLEN   DC    AL2(*-*)                 string length
  2232.          SPACE
  2233.          DS    0D                  ATTN Plist to stack description
  2234. STKLIST  DC    CL8'ATTN'                command name for SVC 202
  2235. STKORDR  DC    CL4'FIFO'                LIFO or FIFO
  2236. STKLEN   DC    AL1(*-*)                 string length
  2237.          DC    AL3(DATABUFF+1)          string length
  2238.          SPACE
  2239. STEMNAME DS    1D                  Stem variable names
  2240. HDREC    DS    16D                 File header info.  (128 bytes)
  2241.          ORG   HDREC               Define header fields
  2242. HDVER    DS    1X                       version byte
  2243. HDFNLEN  DS    1X                       length of filename
  2244. HDFN     DS    63C                      filename
  2245. *                                       start of Finder Info record
  2246. HDFTYP   DS    4C                       file type
  2247. HDFCREAT DS    4C                       file creator
  2248. HDFLAGS  DS    1X                       finder flags
  2249. HDFLAG2  DS    1X                       second flag byte
  2250. HDVPOS   DS    2X                       vertical position
  2251. HDHPOS   DS    2X                       horizontal position
  2252. HDID     DS    2X                       window or folder ID
  2253. *                                       end of Finder Info record
  2254. HDPFLAG  DS    1X                       "protected" flag
  2255. HDZERO2  DS    1X                       zero
  2256. HDDATALN DS    4X                       data fork length
  2257. HDRSCLN  DS    4X                       resource fork length
  2258. HDCRDATE DS    4X                       creation date
  2259. HDMDDATE DS    4X                       last modified date
  2260. HDZERO3  DS    29X                      zero fill
  2261.          ORG
  2262. BINLEN   DS    1F                  Length of data in BINBUFF
  2263. BINXTADR DS    1A                  Addr. for processing left over bits
  2264. BINOFF   DS    1F                  Offset into BINBUFF for GETSTR
  2265. RDOFF    DS    1F                  Offset into READBUFF for GTBINLIN
  2266. EOFPOS   DS    1F                  Position of EOFCHAR in current line
  2267. CHRTOTAL DS    1F                  Total char. read by GETLINE
  2268. CPS      DS    1F                  Xfer rate chars./sec. or zero
  2269. EXPLEN   DS    1F                  No. of bytes in EXPBUFF
  2270. WRLEN    DS    1F                  HQX output line length
  2271. STEMSIZE DS    1F                  Length of STEMNAME
  2272. FRASCADR DS    A                   A(ASCII to EBCDIC table)
  2273. TOASCADR DS    A                   A(EBCDIC to ASCII table)
  2274. OPRTAB   DS    0F                  Operand processing table
  2275.          DC    CL8'?',AL4(QUESOPR)
  2276.          DC    CL8'CHECK',AL4(CHKOPR)
  2277.          DC    CL8'CONVERT',AL4(CVTOPR)
  2278.          DC    CL8'DESCRIBE',AL4(DESCOPR)
  2279.          DC    8X'FF',AL4(-1)
  2280. OPTTAB   DS    0F                  Option processing table
  2281.          DC    CL8'FIFO',AL4(STKOPT)
  2282.          DC    CL8'LIFO',AL4(LIFOOPT)
  2283.          DC    CL8'RATE',AL4(RATEOPT)
  2284.          DC    CL8'STACK',AL4(STKOPT)
  2285.          DC    CL8'STEM',AL4(STEMOPT)
  2286.          DC    CL8'TO',AL4(TOOPT)
  2287.          DC    8X'FF',AL4(-1)
  2288. CRCVAL   DS    1H                  Calculated CRC
  2289. CMPLBYTE DS    1X                  Last byte for compression
  2290. CMPCNT   DS    1X                  Compression count
  2291. CMPCHAR  DS    1C                  Character for compression
  2292. BINLAST  DS    1X                  Last character in BINBUFF
  2293. BINEXTRA DS    1X                  Left over binary data
  2294. OPRCODE  DS    1C                  Code for first operand
  2295. EOFCHAR  DS    1C                  Invalid char. GETLINE stopped at
  2296. CMPMODE  DS    1X                  Current state for HQX compression
  2297. HCMPCHAR DS    1C                  Last character for HQX compression
  2298. CMPCOUNT DS    1X                  Character count for HQX comp.
  2299. FLAGS    DS    1X                  Flag byte
  2300. MACBIN   EQU   X'01'                    Input file is MacBinary
  2301. RDOPEN   EQU   X'02'                    Input file is open
  2302. WROPEN   EQU   X'04'                    Output file is open
  2303. HQXCOLON EQU   X'08'                    Found first colon for HQX file
  2304. HQXEOF   EQU   X'10'                    Found eof colon for HQX file
  2305. X90DATA  EQU   X'20'                    Use data byte from last X'90'
  2306. STKDESC  EQU   X'40'                    Stack description output
  2307. STKLIFO  EQU   X'80'                    Stack output LIFO
  2308. FLAGS2   DS    1X                  Second flag byte
  2309. EXECVAR  EQU   X'01'                    Return header info in vars.
  2310. NOCOMMA  EQU   X'02'                    Suppress commas for NUMTOSTR
  2311. FLAGTEXT DC    C'LockInvsBndlSystBozoBusyChngInit'
  2312.          DC    C'CachShrdSwitNoSwRsv3Rsv2OwnADesk'
  2313.          LTORG
  2314.          DROP  R11,R12,R13
  2315.          EJECT
  2316. TOASCBRN DS 0D            BROWN'S CP EBCDIC TO ASCII TRANSLATE TABLE
  2317.          DC X'000102037F097F7F7F7F7F0B0C0D0E0F'   *....".""""".....*
  2318.          DC X'101112137F0A087F18197F7F1C1D1E1F'   *....".."..""....*
  2319.          DC X'7F7F1C7F7F0A171B7F7F7F7F7F050607'   *"".""..."""""...*
  2320.          DC X'7F7F167F7F1E7F047F7F7F1314157F1A'   *"".""."."""...".*
  2321.          DC X'207F7F7F7F7F7F7F7F7F5B2E3C282B5E'   *."""""""""$....;*
  2322.          DC X'267F7F7F7F7F7F7F7F7F21242A293B7E'   *.""""""""".....=*
  2323.          DC X'2D2F7F7F7F7F7F7F7F7F7C2C255F3E3F'   *..""""""""@..~..*
  2324.          DC X'7F7F7F7F7F7F7F7F607F3A2340273D22'   *""""""""-".. ...*
  2325.          DC X'7F6162636465666768697F7B7F7F7F7F'   *"/........"#""""*
  2326.          DC X'7F6A6B6C6D6E6F7071727F7D7F7F7F7F'   *".,%_>?..."'""""*
  2327.          DC X'7F7F737475767778797A7F7F7F5B7F7F'   *"".......:"""$""*
  2328.          DC X'7F7F7F7F7F7F7F7F7F7F7F7F7F5D7F7F'   *""""""""""""")""*
  2329.          DC X'7F4142434445464748497F7F7F7F7F7F'   *".........""""""*
  2330.          DC X'7F4A4B4C4D4E4F5051527F7F7F7F7F7F'   *"..<(+|&..""""""*
  2331.          DC X'5C7F535455565758595A7F7F7F7F7F7F'   **".......!""""""*
  2332.          DC X'303132333435363738397F7F7F7F7F7F'   *..........""""""*
  2333.          SPACE
  2334. FRASCBRN DS    0D         BROWN'S CP ASCII TO EBCDIC TRANSLATE TABLE
  2335.          DC    X'00010203372D2E2F1605250B0C0D0E0F'
  2336.          DC    X'FF11123B3C3D322618193F271C1D1E1F'
  2337.          DC    X'405A7F7B5B6C507D4D5D5C4E6B604B61'
  2338.          DC    X'F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F'
  2339.          DC    X'7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6'
  2340.          DC    X'D7D8D9E2E3E4E5E6E7E8E9ADE0BD4F6D'
  2341.          DC    X'78818283848586878889919293949596'
  2342.          DC    X'979899A2A3A4A5A6A7A8A98B6A9B5F07'
  2343.          DC    X'00010203372D2E2F1605250B0C0D0E0F'
  2344.          DC    X'FF11123B3C3D322618193F271C1D1E1F'
  2345.          DC    X'405A7F7B5B6C507D4D5D5C4E6B604B61'
  2346.          DC    X'F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F'
  2347.          DC    X'7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6'
  2348.          DC    X'D7D8D9E2E3E4E5E6E7E8E9ADE0BD4F6D'
  2349.          DC    X'78818283848586878889919293949596'
  2350.          DC    X'979899A2A3A4A5A6A7A8A98B6A9B5F07'
  2351.          EJECT
  2352. TOASCSTD DS 0D                   STANDARD CP EBCDIC TO ASCII TABLE
  2353.          DC X'000102037F097F7F7F7F7F0B0C0D0E0F' *....".""""".....*
  2354.          DC X'101112137F0A080018197F7F1C1D1E1F' *....".....""....*
  2355.          DC X'7F7F7F7F7F0A171B7F7F7F7F7F050607' *"""""..."""""...*
  2356.          DC X'7F7F167F7F7F7F047F7F7F7F14157F1A' *""."""".""""..".*
  2357.          DC X'207F7F7F7F7F7F7F7F7F7F2E3C282B7C' *.""""""""""....@*
  2358.          DC X'267F7F7F7F7F7F7F7F7F21242A293B5E' *.""""""""".....;*
  2359.          DC X'2D2F7F7F7F7F7F7F7F7F7C2C255F3E3F' *..""""""""@..~..*
  2360.          DC X'7F7F7F7F7F7F7F7F7F603A2340273D22' *"""""""""-.....*
  2361.          DC X'7F6162636465666768697F7F7F7F7F7F' *"/........""""""*
  2362.          DC X'7F6A6B6C6D6E6F7071727F7F7F7F7F7F' *".,%_>?...""""""*
  2363.          DC X'7F7E737475767778797A7F7F7F5B7F7F' *"=.......:"""$""*
  2364.          DC X'7F7F7F7F7F7F7F7F7F7F7F7F7F5D7F7F' *""""""""""""")""*
  2365.          DC X'7B4142434445464748497F7F7F7F7F7F' *#.........""""""*
  2366.          DC X'7D4A4B4C4D4E4F5051527F7F7F7F7F7F' *'.<(+|&..""""""*
  2367.          DC X'5C7F535455565758595A7F7F7F7F7F7F' **".......!""""""*
  2368.          DC X'303132333435363738397F7F7F7F7F7F' *..........""""""*
  2369.          SPACE
  2370. FRASCSTD DS    0D                STANDARD CP ASCII TO EBCDIC TABLE
  2371.          DC    X'00010203372D2E2F1605250B0C0D0E0F'
  2372.          DC    X'101112133C3D322618193F271C1D1E1F'
  2373.          DC    X'405A7F7B5B6C507D4D5D5C4E6B604B61'
  2374.          DC    X'F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F'
  2375.          DC    X'7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6'
  2376.          DC    X'D7D8D9E2E3E4E5E6E7E8E9ADE0BD5F6D'
  2377.          DC    X'79818283848586878889919293949596'
  2378.          DC    X'979899A2A3A4A5A6A7A8A9C04FD0A107'
  2379.          DC    X'00010203372D2E2F1605250B0C0D0E0F'
  2380.          DC    X'101112133C3D322618193F271C1D1E1F'
  2381.          DC    X'405A7F7B5B6C507D4D5D5C4E6B604B61'
  2382.          DC    X'F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F'
  2383.          DC    X'7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6'
  2384.          DC    X'D7D8D9E2E3E4E5E6E7E8E9ADE0BD5F6D'
  2385.          DC    X'79818283848586878889919293949596'
  2386.          DC    X'979899A2A3A4A5A6A7A8A9C04FD0A107'
  2387.          EJECT
  2388. VALIDTAB DS    256X                TRT table for valid characters
  2389. *                                  (Filled-in at initialization)
  2390. CMPTAB   DC    256X'00'            TRT table for X'90'
  2391.          ORG   CMPTAB+X'90'
  2392.          DC    X'FF'
  2393.          ORG
  2394.          SPACE
  2395. ASCTOBIN DS    0D
  2396.          DC    128X'FF'
  2397.          ORG   ASCTOBIN+X'21'
  2398.          DC    X'00010203040506070809'  ! " # $ % & ' ( ) *
  2399.          DC    X'0A0B0C'                + , -
  2400.          ORG   ASCTOBIN+X'30'
  2401.          DC    X'0D0E0F10111213'        0 1 2 3 4 5 6
  2402.          ORG   ASCTOBIN+X'38'
  2403.          DC    X'1415'                  8 9
  2404.          ORG   ASCTOBIN+X'40'
  2405.          DC    X'161718191A1B1C1D1E1F'  @ A B C D E F G H I
  2406.          DC    X'2021222324'            J K L M N
  2407.          ORG   ASCTOBIN+X'50'
  2408.          DC    X'25262728292A2B'        P Q R S T U V
  2409.          ORG   ASCTOBIN+X'58'
  2410.          DC    X'2C2D2E2F'              X Y Z [
  2411.          ORG   ASCTOBIN+X'60'
  2412.          DC    X'30313233343536'        i a b c d e f
  2413.          ORG   ASCTOBIN+X'68'
  2414.          DC    X'3738393A3B3C'          h i j k l m
  2415.          ORG   ASCTOBIN+X'70'
  2416.          DC    X'3D3E3F'                p q r
  2417.          ORG
  2418. *                ! " # $ % & ' ( ) * + , - 0 1 2 3 4 5 6 8 9 @
  2419. BINTOASC DC    X'2122232425262728292A2B2C2D30313233343536383940'
  2420. *                A B C D E F G H I J K L M N P Q R S T U V X Y
  2421.          DC    X'4142434445464748494A4B4C4D4E505152535455565859'
  2422. *                Z [ i a b c d e f h i j k l m p q r
  2423.          DC    X'5A5B6061626364656668696A6B6C6D707172'
  2424. HQXMSG   DC    C'(This file must be converted with BinHex 4.0)'
  2425. HQXMSGL  EQU   *-HQXMSG
  2426.          SPACE
  2427. VARTAB   DS    0A                  Address table for REXX var. names
  2428.          DC    A(VAR1)
  2429.          DC    A(VAR2)
  2430.          DC    A(VAR3)
  2431.          DC    A(VAR4)
  2432.          DC    A(VAR5)
  2433.          DC    A(VAR6)
  2434.          DC    A(VAR7)
  2435.          DC    A(VAR8)
  2436.          DC    A(VAR9)
  2437.          DC    A(VAR10)
  2438.          DC    A(VAR11)
  2439.          DC    A(VAR12)
  2440. AVAR13   DC    A(VAR13)
  2441. AVAR14   DC    A(VAR14)
  2442. VAR1     DC    AL1(VAR1L),C'FN'         CMS filename
  2443. VAR1L    EQU   *-VAR1-1
  2444. VAR2     DC    AL1(VAR2L),C'FT'         CMS filetype
  2445. VAR2L    EQU   *-VAR2-1
  2446. VAR3     DC    AL1(VAR3L),C'FM'         CMS filemode
  2447. VAR3L    EQU   *-VAR3-1
  2448. VAR4     DC    AL1(VAR4L),C'FORMAT'     MacBinary or BinHex
  2449. VAR4L    EQU   *-VAR4-1
  2450. VAR5     DC    AL1(VAR5L),C'NAME'       Mac filename
  2451. VAR5L    EQU   *-VAR5-1
  2452. VAR6     DC    AL1(VAR6L),C'TYPE'       Mac type
  2453. VAR6L    EQU   *-VAR6-1
  2454. VAR7     DC    AL1(VAR7L),C'CREATOR'    Mac creator
  2455. VAR7L    EQU   *-VAR7-1
  2456. VAR8     DC    AL1(VAR8L),C'FLAGS'      Mac flags
  2457. VAR8L    EQU   *-VAR8-1
  2458. VAR9     DC    AL1(VAR9L),C'DATASIZE'   Mac data fork size
  2459. VAR9L    EQU   *-VAR9-1
  2460. VAR10    DC    AL1(VAR10L),C'RESCSIZE'  Mac resource fork size
  2461. VAR10L   EQU   *-VAR10-1
  2462. VAR11    DC    AL1(VAR11L),C'CRDATE'    Mac creation date
  2463. VAR11L   EQU   *-VAR11-1
  2464. VAR12    DC    AL1(VAR12L),C'MDDATE'    Mac last modified date
  2465. VAR12L   EQU   *-VAR12-1
  2466. VAR13    DC    AL1(VAR13L),C'CHARCNT'   Total character count
  2467. VAR13L   EQU   *-VAR13-1
  2468. VAR14    DC    AL1(VAR14L),C'TIMEEST'   Dowload time estimate
  2469. VAR14L   EQU   *-VAR14-1
  2470.          SPACE
  2471. EXPBUFF  DS    6D                  48-byte HQX expansion buffer
  2472. WRITBUFF DS    8D                  64-byte disk output buffer
  2473. DATABUFF DS    16D                 128-byte work buffer
  2474. BINBUFF  DS    25D                 Binary from READBUFF
  2475. READBUFF DS    32D                 256-byte disk input buffer
  2476.          ADT
  2477.          FSTB
  2478.          FVS
  2479.          NUCON
  2480.          SHVBLOCK
  2481.          END
  2482. ---------- end of BINHEX ASSEMBLE -----------------------------------
  2483. ---------- start of BINHEX HELPCMS: 224 lines follow ----------------
  2484. ..fo off
  2485. ..cs 1 on
  2486.  
  2487. BINHEX
  2488.  
  2489. Use the  BINHEX command  to work  with Macintosh  files containing  binary data
  2490. which are stored  in CMS.   BINHEX may be  used with HQX files,   such as those
  2491. created by BinHex 4.0 on the Macintosh, and also with BIN files,  such as those
  2492. created by BinHex  5.0.   BINHEX checks files in these  formats,  describes the
  2493. contents of the files, and converts between the two formats.
  2494. ..cs 1 off
  2495. ..cs 2 on
  2496. The format of the BINHEX command is:
  2497.  
  2498. ?~~~~~~~~~~]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\
  2499. k          k                                                                  k
  2500. k BINHEX   k ? | Check | Describe | COnvert  fn <ft <fm >>   [(options...[)]] k
  2501. k          k                                                                  k
  2502. k          k Options:                                                         k
  2503. k          k     ?           \  ?           \  ?           \                  k
  2504. k          k     kTo fm      k  kStack      k  kFifo       k                  k
  2505. k          k     kRate cps   k  kLifo       k  kSTEm stm   k                  k
  2506. k          k     >           ;  >           ;  >           ;                  k
  2507. k          k                                                                  k
  2508. >~~~~~~~~~~[~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
  2509. ..cs 2 off
  2510. ..cs 3 on
  2511.  
  2512. OPERANDS
  2513.  
  2514. ?         causes BINHEX  to type  a brief  description of  the command  format,
  2515.           including all the valid operands and options.  When "?" is specified,
  2516.           the remainder of the command line is ignored.
  2517.  
  2518. Check     cause BINHEX to check the input file  for errors,  such as missing or
  2519.           corrupted data.   BINHEX will either report  there are no errors,  or
  2520.           respond with an  error message describing the  problem.   BINHEX also
  2521.           checks  the  input file  when  the  Describe  or COnvert  operand  is
  2522.           specified.
  2523.  
  2524. Describe  causes BINHEX to display information about the input file,  including
  2525.           the full Macintosh filename, the type, creator, flags values, and the
  2526.           sizes of the  data and resource forks.   See  the "Responses" section
  2527.           below for examples of the information which is displayed.
  2528.  
  2529. COnvert   causes BINHEX  to convert  the input  file from  BinHex to  MacBinary
  2530.           format or vice-versa.    The resulting file has the  same filename as
  2531.           the input file,  and a filetype  of either BIN (for MacBinary format)
  2532.           or HQX (for BinHex format).   The file is written to the same disk as
  2533.           the input file, unless the "To" option has been specified.
  2534.  
  2535. fn        specifies the filename of the input file.
  2536.  
  2537. ft        specifies the filetype  of the input file.   When "ft"  is omitted or
  2538.           specified as "*",  all filetypes will be searched to find a match for
  2539.           "fn".
  2540.  
  2541. fm        specifies the filemode  of the input file.   When "fm"  is omitted or
  2542.           specified as  "*",  all accessed  disks will  be searched for  a file
  2543.           matching "fn" and "ft".
  2544.  
  2545. OPTIONS
  2546.  
  2547. To fm     specifies the disk to which the output  file will be written when the
  2548.           "COnvert" operand is  specified.   When "To" is  omitted,  the output
  2549.           file is written to the same disk as the input file.
  2550.  
  2551. Rate cps  specifies a file transfer rate in characters per second.  When a rate
  2552.           is specified,  the  information displayed by the  "Describe" function
  2553.           will include an estimate of the time required to download the file.
  2554.  
  2555. Stack     cause the output  from the "Describe" function to be  stacked in FIFO
  2556.           order.  "Fifo" is a synonym for "Stack".
  2557.  
  2558. Lifo      causes the output from the "Describe"  function to be stacked in LIFO
  2559.           order.
  2560.  
  2561. Fifo      cause the output  from the "Describe" function to be  stacked in FIFO
  2562.           order.  "Stack" is a synonym for "Fifo".
  2563.  
  2564. STEm stm  causes the output from the "Describe"  function to be stored directly
  2565.           into REXX  or EXEC2 variables.    "stm" is the  name of the  stem for
  2566.           these variables,   i.e.  the characters  preceding a period  in their
  2567.           names.   Only  the first eight  characters of "stm"  are significant.
  2568.           The following variables are defined:
  2569.  
  2570.                stm.FN         CMS filename
  2571.                stm.FT         CMS filetype
  2572.                stm.FM         CMS filemode
  2573.                stm.FORMAT     BinHex or MacBinary
  2574.                stm.NAME       Mac filename
  2575.                stm.TYPE       Mac type
  2576.                stm.CREATOR    Mac creator
  2577.                stm.FLAGS      Mac flags
  2578.                stm.DATASIZE   Mac data fork size
  2579.                stm.RESCSIZE   Mac resource fork size
  2580.                stm.CRDATE     Mac creation date
  2581.                stm.MDDATE     Mac last modified date
  2582.                stm.CHARCNT    Total character count
  2583.                stm.TIMEEST    Download time estimate
  2584.  
  2585.           The  creation and  last modified  dates  are not  defined for  BinHex
  2586.           format files,   which do  not include  them.   The  time estimate  is
  2587.           defined only when the Rate option has been specified.
  2588.  
  2589. USING THE BINHEX COMMAND
  2590.  
  2591. The BINHEX  command allows  Macintosh users to  obtain information  about files
  2592. stored in CMS which would ordinarily not  be available until the files had been
  2593. downloaded to a  Macintosh.   The Check function  verifies that a file  will be
  2594. accepted  by BinHex  on  the Macintosh,   and  the  Describe function  provides
  2595. detailed information about a file.  With this information, a Macintosh user can
  2596. often avoid  spending time  downloading unwanted files  or files  which contain
  2597. errors.   The COnvert function provides conversion between the two file formats
  2598. BINHEX accepts:   BinHex format  and MacBinary  format.   Conversion  is useful
  2599. because each of these formats offers advantages for storing Macintosh programs.
  2600.  
  2601. BinHex format is used by BinHex 4.0 on the Macintosh.  It consists of a header,
  2602. the data  fork,  and  the resource fork  of a  Macintosh file,   compressed and
  2603. converted to printable characters.   Converting a file from binary to printable
  2604. characters increases its size (in spite  of the inclusion of file compression).
  2605. However,  since  they contain only printable  characters,  BinHex files  can be
  2606. included in electronic mail,  and can be  uploaded and downloaded in nearly any
  2607. environment.   In  CMS,  BinHex  files usually  are given  filetypes containing
  2608. "HQX", and may have fixed or variable-length records.   The files usually begin
  2609. with the line
  2610.  
  2611.      (This file must be converted with BinHex 4.0)
  2612.  
  2613. MacBinary format is used by BinHex 5.0 and MacTerminal on the Macintosh.  It is
  2614. similar to BinHex format,  but retains the file contents in binary form instead
  2615. of  converting  to printable  characters.    It  also  includes the  dates  the
  2616. Macintosh  file was  created  and last  modified,  and  some  extra flag  bits.
  2617. MacBinary is the  most compact format for storing a  Macintosh file.   However,
  2618. because MacBinary files retain binary data, they can be uploaded and downloaded
  2619. only by programs which  use an 8-bit data path.   Usually,  such  a path is not
  2620. available for VM/CMS  systems.   Programs such as Kermit can  simulate an 8-bit
  2621. path using  printable characters,   but only at  the expense  of a  much longer
  2622. transfer time.   MacBinary files in CMS  usually are given filetypes containing
  2623. "BIN".  They consist of fixed-length 128-byte records.
  2624.  
  2625. USAGE NOTES
  2626.  
  2627.   1) Although the filetype of the input file will usually indicate which format
  2628.      it  is  in,   BINHEX  determines  the   file's  format  by  examining  its
  2629.      characteristics.   If the file has  fixed-length 128-byte records,  BINHEX
  2630.      assumes MacBinary format.  Otherwise, BINHEX assumes BinHex format.
  2631.  
  2632.   2) The data in a BinHex format file begins  with a line containing a colon in
  2633.      column one,  and  ends with a line  having a colon as  the last character.
  2634.      CMS BINHEX skips  any other lines in  the file.   However,  BinHex  on the
  2635.      Macintosh only skips  the comment line "(This file must  be converted with
  2636.      BinHex 4.0)".   Thus,  even when the Check function reports no errors,  it
  2637.      may still  be necessary to  delete extraneous  lines from the  BinHex file
  2638.      before BinHex on the Macintosh will accept the file.
  2639.  
  2640.   3) BinHex  format  files do  not  contain  all  the information  included  in
  2641.      MacBinary files.  In particular, the creation and last modified dates, and
  2642.      some flag bits are not stored.  As a result, this information is lost when
  2643.      the COnvert function is used to convert from MacBinary to BinHex format.
  2644.  
  2645.   4) BINHEX cannot  detect if  the input  file is  not in  either MacBinary  or
  2646.      BinHex format.   In this case,  BINHEX will  usually assume the file is in
  2647.      BinHex format,  and give an "unexpected end-of-file" message when it fails
  2648.      to find the first line of BinHex data.
  2649.  
  2650.   5) For a BinHex file, the maximum line length BINHEX can process is 256.
  2651.  
  2652. RESPONSES
  2653.  
  2654. 'fn ft fm': No errors detected.
  2655.  
  2656.           This is the normal response from  the Check function.   This response
  2657.           is omitted when BINHEX is called from a CMS command,  or from an exec
  2658.           file with "address COMMAND" in effect.
  2659.  
  2660. File: 'STARS16 HQX T1'  Format: BinHex
  2661. Filename: 'Stars 1.6'
  2662. Type: 'DFIL'  Creator: 'DMOV'  Flags: none
  2663. Data fork size: 0; Resource fork size: 6,054
  2664. Character count: 10,140.
  2665.  
  2666.           This is  the response from  the Describe  function for a  BinHex file
  2667.           when the  Rate option is  not used.    This is the  shortest possible
  2668.           description.
  2669.  
  2670. File: 'TERM412 BIN M1'  Format: MacBinary
  2671. Filename: 'Term 4.12'
  2672. Type: 'APPL'  Creator: 'TRMA'  Flags: Bndl+Init
  2673. Data fork size: 0; Resource fork size: 52,947
  2674.       Created: Thu, May 28, 1987  2:01:25 AM
  2675. Last Modified: Thu, May 28, 1987  2:02:04 AM
  2676. Character count: 53,120 (4 minutes, 55 seconds at 180 cps).
  2677.  
  2678.           This is the response from the  Describe function for a MacBinary file
  2679.           when  the  Rate  option  is used.    This  is  the  longest  possible
  2680.           description.
  2681.  
  2682. OTHER MESSAGES AND RETURN CODES
  2683.  
  2684.      DMSBIN631E 'STEM' option is only available from an EXEC2 or REXX exec.
  2685.                 RC=4
  2686.      DMSBIN001E Error in command after 'token'.  RC=24
  2687.      DMSBIN002I Issue BINHEX ? or HELP CMS BINHEX for more information.
  2688.      DMSBIN003E Invalid option 'xxxxxxxx'.  RC=24
  2689.      DMSBIN010E Invalid rate 'xxxxxxxx'.  RC=24
  2690.      DMSBIN048E Invalid mode 'xxxxxxxx'.  RC=24
  2691.      DMSBIN637E Missing value for the 'STEM' option.  RC=24
  2692.      DMSBIN002E File 'fn ft fm' not found.  RC=28
  2693.      DMSBIN024E File 'fn ft fm' already exists.  RC=28
  2694.      DMSBIN044E Record length exceeds allowable maximum.  RC=32
  2695.      DMSBIN005E Invalid character 'x' in 'fn ft fm' at line mmmmmm position
  2696.                 nnn.  RC=36
  2697.      DMSBIN006E Unexpected end-of-file reading 'fn ft fm'.  RC=36
  2698.      DMSBIN037E Disk 'mode' is read-only.  RC=36
  2699.      DMSBIN069E Disk 'mode' not accessed.  RC=36
  2700.      DMSBIN007E 'fn ft fm': CRC error for BinHex header.  RC=44
  2701.      DMSBIN008E 'fn ft fm': CRC error for BinHex data fork.  RC=44
  2702.      DMSBIN009E 'fn ft fm': CRC error for BinHex resource fork.  RC=44
  2703.      DMSBIN104S Error 'nn' reading file 'fn ft fm' from disk.  RC=1nn
  2704.      DMSBIN105S Error 'nn' writing file 'fn ft fm' on disk.  RC=1nn
  2705.      DMSBIN632E Error setting EXEC variable: RC=nnnnn from 'EXECCOMM'.  RC=200
  2706.  
  2707. ..cs 3 off
  2708. ---------- end of BINHEX HELPCMS ------------------------------------
  2709. ---------- start of XMDMGEN C: 62 lines follow ----------------------
  2710. /* This program generates the XMODEM CRC table in XMDMTAB ASSEMBLE. */
  2711. /* Peter DiCamillo, June, 1987 */
  2712.  
  2713. #include "stdio.h"
  2714.  
  2715. main()
  2716. ,
  2717. FILE *io;
  2718. unsigned int array[256];
  2719. register char x1, x2, x3, x4, x5, x6, x7, x8;
  2720. int count;
  2721. int i, j, k;
  2722. char ioline[132], iobuff[80];
  2723.  
  2724. count = 0;
  2725.  
  2726. for (x8=0; x8 < 2; x8++)
  2727.  for (x7=0; x7 < 2; x7++)
  2728.   for (x6=0; x6 < 2; x6++)
  2729.    for (x5=0; x5 < 2; x5++)
  2730.     for (x4=0; x4 < 2; x4++)
  2731.      for (x3=0; x3 < 2; x3++)
  2732.       for (x2=0; x2 < 2; x2++)
  2733.        for (x1=0; x1 < 2; x1++) ,
  2734.         array[count] = 0;
  2735.         if (x8 ~ x4) array[count] += 0x8000;
  2736.         if (x7 ~ x3) array[count] += 0x4000;
  2737.         if (x6 ~ x2) array[count] += 0x2000;
  2738.         if (x8 ~ x5 ~ x1) array[count] += 0x1000;
  2739.         if (x7) array[count] += 0x0800;
  2740.         if (x6) array[count] += 0x0400;
  2741.         if (x5) array[count] += 0x0200;
  2742.         if (x8 ~ x4) array[count] += 0x0100;
  2743.         if (x8 ~ x7 ~ x3) array[count] += 0x0080;
  2744.         if (x7 ~ x6 ~ x2) array[count] += 0x0040;
  2745.         if (x6 ~ x5 ~ x1) array[count] += 0x0020;
  2746.         if (x5) array[count] += 0x0010;
  2747.         if (x8 ~ x4) array[count] += 0x0008;
  2748.         if (x7 ~ x3) array[count] += 0x0004;
  2749.         if (x6 ~ x2) array[count] += 0x0002;
  2750.         if (x5 ~ x1) array[count] += 0x0001;
  2751.         count++;
  2752.         -
  2753. /* Output assemble file with the table */
  2754.  
  2755. io = fopen("xmdmtab assemble a (lrecl 80 recfm f","w");
  2756. j = 6;      /* number of contants on current line */
  2757. strcpy(ioline,"XMDMTAB  CSECT");
  2758. for (i = 0; i < 256; i++) ,
  2759.     if (j == 6) ,
  2760.        fprintf(io, "%s\n", ioline);
  2761.        j = 0;
  2762.        strcpy(ioline,"         DC    ");
  2763.        -
  2764.     if (j != 0) strcat(ioline,",");
  2765.     sprintf(iobuff,"X'%04x'",array[i]);
  2766.     strcat(ioline,iobuff);
  2767.     j++;
  2768.     -
  2769. if (j != 0) fprintf(io, "%s\n", ioline);
  2770. fclose(io);
  2771. -
  2772. ---------- end of XMDMGEN C -----------------------------------------
  2773. ---------- start of XMDMTAB ASSEMBLE: 46 lines follow ---------------
  2774. * Table for calculating XMODEM CRC; generated by XMDMGEN C
  2775. XMDMTAB  CSECT                     TABLE FOR GENERATING XMODEM CRC
  2776.          DC    X'0000',X'1021',X'2042',X'3063',X'4084',X'50A5'
  2777.          DC    X'60C6',X'70E7',X'8108',X'9129',X'A14A',X'B16B'
  2778.          DC    X'C18C',X'D1AD',X'E1CE',X'F1EF',X'1231',X'0210'
  2779.          DC    X'3273',X'2252',X'52B5',X'4294',X'72F7',X'62D6'
  2780.          DC    X'9339',X'8318',X'B37B',X'A35A',X'D3BD',X'C39C'
  2781.          DC    X'F3FF',X'E3DE',X'2462',X'3443',X'0420',X'1401'
  2782.          DC    X'64E6',X'74C7',X'44A4',X'5485',X'A56A',X'B54B'
  2783.          DC    X'8528',X'9509',X'E5EE',X'F5CF',X'C5AC',X'D58D'
  2784.          DC    X'3653',X'2672',X'1611',X'0630',X'76D7',X'66F6'
  2785.          DC    X'5695',X'46B4',X'B75B',X'A77A',X'9719',X'8738'
  2786.          DC    X'F7DF',X'E7FE',X'D79D',X'C7BC',X'48C4',X'58E5'
  2787.          DC    X'6886',X'78A7',X'0840',X'1861',X'2802',X'3823'
  2788.          DC    X'C9CC',X'D9ED',X'E98E',X'F9AF',X'8948',X'9969'
  2789.          DC    X'A90A',X'B92B',X'5AF5',X'4AD4',X'7AB7',X'6A96'
  2790.          DC    X'1A71',X'0A50',X'3A33',X'2A12',X'DBFD',X'CBDC'
  2791.          DC    X'FBBF',X'EB9E',X'9B79',X'8B58',X'BB3B',X'AB1A'
  2792.          DC    X'6CA6',X'7C87',X'4CE4',X'5CC5',X'2C22',X'3C03'
  2793.          DC    X'0C60',X'1C41',X'EDAE',X'FD8F',X'CDEC',X'DDCD'
  2794.          DC    X'AD2A',X'BD0B',X'8D68',X'9D49',X'7E97',X'6EB6'
  2795.          DC    X'5ED5',X'4EF4',X'3E13',X'2E32',X'1E51',X'0E70'
  2796.          DC    X'FF9F',X'EFBE',X'DFDD',X'CFFC',X'BF1B',X'AF3A'
  2797.          DC    X'9F59',X'8F78',X'9188',X'81A9',X'B1CA',X'A1EB'
  2798.          DC    X'D10C',X'C12D',X'F14E',X'E16F',X'1080',X'00A1'
  2799.          DC    X'30C2',X'20E3',X'5004',X'4025',X'7046',X'6067'
  2800.          DC    X'83B9',X'9398',X'A3FB',X'B3DA',X'C33D',X'D31C'
  2801.          DC    X'E37F',X'F35E',X'02B1',X'1290',X'22F3',X'32D2'
  2802.          DC    X'4235',X'5214',X'6277',X'7256',X'B5EA',X'A5CB'
  2803.          DC    X'95A8',X'8589',X'F56E',X'E54F',X'D52C',X'C50D'
  2804.          DC    X'34E2',X'24C3',X'14A0',X'0481',X'7466',X'6447'
  2805.          DC    X'5424',X'4405',X'A7DB',X'B7FA',X'8799',X'97B8'
  2806.          DC    X'E75F',X'F77E',X'C71D',X'D73C',X'26D3',X'36F2'
  2807.          DC    X'0691',X'16B0',X'6657',X'7676',X'4615',X'5634'
  2808.          DC    X'D94C',X'C96D',X'F90E',X'E92F',X'99C8',X'89E9'
  2809.          DC    X'B98A',X'A9AB',X'5844',X'4865',X'7806',X'6827'
  2810.          DC    X'18C0',X'08E1',X'3882',X'28A3',X'CB7D',X'DB5C'
  2811.          DC    X'EB3F',X'FB1E',X'8BF9',X'9BD8',X'ABBB',X'BB9A'
  2812.          DC    X'4A75',X'5A54',X'6A37',X'7A16',X'0AF1',X'1AD0'
  2813.          DC    X'2AB3',X'3A92',X'FD2E',X'ED0F',X'DD6C',X'CD4D'
  2814.          DC    X'BDAA',X'AD8B',X'9DE8',X'8DC9',X'7C26',X'6C07'
  2815.          DC    X'5C64',X'4C45',X'3CA2',X'2C83',X'1CE0',X'0CC1'
  2816.          DC    X'EF1F',X'FF3E',X'CF5D',X'DF7C',X'AF9B',X'BFBA'
  2817.          DC    X'8FD9',X'9FF8',X'6E17',X'7E36',X'4E55',X'5E74'
  2818.          DC    X'2E93',X'3EB2',X'0ED1',X'1EF0'
  2819.          END
  2820. ---------- end of XMDMTAB ASSEMBLE ----------------------------------
  2821.